2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2005
7 Copyright (C) Simo Sorce 2005-2008
8 Copyright (C) Matthieu Patou <mat@matws.net> 2011
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <ldb_module.h>
27 #include "system/time.h"
28 #include "dsdb/samdb/samdb.h"
30 #include "dsdb/samdb/ldb_modules/util.h"
31 #include "libcli/security/security.h"
32 #include "librpc/ndr/libndr.h"
33 #include "auth/auth.h"
34 #include "param/param.h"
35 #include "lib/messaging/irpc.h"
36 #include "librpc/gen_ndr/ndr_irpc_c.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "cldap_server/cldap_server.h"
39 #include "lib/events/events.h"
43 struct rootdse_private_data
{
44 unsigned int num_controls
;
46 unsigned int num_partitions
;
47 struct ldb_dn
**partitions
;
49 struct tevent_context
*saved_ev
;
50 struct tevent_context
*private_ev
;
53 struct rootdse_context
{
54 struct ldb_module
*module
;
55 struct ldb_request
*req
;
56 struct ldb_val netlogon
;
60 return 1 if a specific attribute has been requested
62 static int do_attribute(const char * const *attrs
, const char *name
)
64 return attrs
== NULL
||
65 ldb_attr_in_list(attrs
, name
) ||
66 ldb_attr_in_list(attrs
, "*");
69 static int do_attribute_explicit(const char * const *attrs
, const char *name
)
71 return attrs
!= NULL
&& ldb_attr_in_list(attrs
, name
);
76 expand a DN attribute to include extended DN information if requested
78 static int expand_dn_in_message(struct ldb_module
*module
, struct ldb_message
*msg
,
79 const char *attrname
, struct ldb_control
*edn_control
,
80 struct ldb_request
*req
)
82 struct ldb_dn
*dn
, *dn2
;
85 struct ldb_request
*req2
;
87 const char *no_attrs
[] = { NULL
};
88 struct ldb_result
*res
;
89 struct ldb_extended_dn_control
*ext_dn
;
90 TALLOC_CTX
*tmp_ctx
= talloc_new(req
);
91 struct ldb_context
*ldb
;
94 struct ldb_message_element
*el
;
96 ldb
= ldb_module_get_ctx(module
);
98 ext_dn
= talloc_get_type(edn_control
->data
, struct ldb_extended_dn_control
);
100 edn_type
= ext_dn
->type
;
103 el
= ldb_msg_find_element(msg
, attrname
);
104 if (!el
|| el
->num_values
== 0) {
108 for (i
= 0; i
< el
->num_values
; i
++) {
111 talloc_free(tmp_ctx
);
115 dn_string
= talloc_strndup(tmp_ctx
, (const char *)v
->data
, v
->length
);
116 if (dn_string
== NULL
) {
117 talloc_free(tmp_ctx
);
118 return ldb_operr(ldb
);
121 res
= talloc_zero(tmp_ctx
, struct ldb_result
);
123 talloc_free(tmp_ctx
);
124 return ldb_operr(ldb
);
127 dn
= ldb_dn_new(tmp_ctx
, ldb
, dn_string
);
129 talloc_free(tmp_ctx
);
130 return ldb_operr(ldb
);
133 ret
= ldb_build_search_req(&req2
, ldb
, tmp_ctx
,
139 res
, ldb_search_default_callback
,
141 LDB_REQ_SET_LOCATION(req2
);
142 if (ret
!= LDB_SUCCESS
) {
143 talloc_free(tmp_ctx
);
147 ret
= dsdb_request_add_controls(req2
, DSDB_FLAG_AS_SYSTEM
|
148 DSDB_SEARCH_SHOW_EXTENDED_DN
);
149 if (ret
!= LDB_SUCCESS
) {
150 talloc_free(tmp_ctx
);
151 return ldb_error(ldb
, ret
, "Failed to add control");
154 ret
= ldb_next_request(module
, req2
);
155 if (ret
== LDB_SUCCESS
) {
156 ret
= ldb_wait(req2
->handle
, LDB_WAIT_ALL
);
159 if (ret
!= LDB_SUCCESS
) {
160 talloc_free(tmp_ctx
);
164 if (!res
|| res
->count
!= 1) {
165 talloc_free(tmp_ctx
);
166 return ldb_operr(ldb
);
169 dn2
= res
->msgs
[0]->dn
;
171 v
->data
= (uint8_t *)ldb_dn_get_extended_linearized(msg
->elements
, dn2
, edn_type
);
172 if (v
->data
== NULL
) {
173 talloc_free(tmp_ctx
);
174 return ldb_operr(ldb
);
176 v
->length
= strlen((char *)v
->data
);
179 talloc_free(tmp_ctx
);
185 see if we are master for a FSMO role
187 static int dsdb_module_we_are_master(struct ldb_module
*module
, struct ldb_dn
*dn
, bool *master
,
188 struct ldb_request
*parent
)
190 const char *attrs
[] = { "fSMORoleOwner", NULL
};
191 TALLOC_CTX
*tmp_ctx
= talloc_new(parent
);
192 struct ldb_result
*res
;
194 struct ldb_dn
*owner_dn
;
196 ret
= dsdb_module_search_dn(module
, tmp_ctx
, &res
,
198 DSDB_FLAG_NEXT_MODULE
|
199 DSDB_FLAG_AS_SYSTEM
|
200 DSDB_SEARCH_SHOW_EXTENDED_DN
,
202 if (ret
!= LDB_SUCCESS
) {
203 talloc_free(tmp_ctx
);
207 owner_dn
= ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module
),
208 tmp_ctx
, res
->msgs
[0], "fSMORoleOwner");
211 talloc_free(tmp_ctx
);
215 ret
= samdb_dn_is_our_ntdsa(ldb_module_get_ctx(module
), dn
, master
);
216 if (ret
!= LDB_SUCCESS
) {
217 ldb_asprintf_errstring(ldb_module_get_ctx(module
), "Failed to confirm if our ntdsDsa is %s: %s",
218 ldb_dn_get_linearized(owner_dn
), ldb_errstring(ldb_module_get_ctx(module
)));
219 talloc_free(tmp_ctx
);
223 talloc_free(tmp_ctx
);
228 add dynamically generated attributes to rootDSE result
230 static int rootdse_add_dynamic(struct rootdse_context
*ac
, struct ldb_message
*msg
)
232 struct ldb_context
*ldb
;
233 struct rootdse_private_data
*priv
= talloc_get_type(ldb_module_get_private(ac
->module
), struct rootdse_private_data
);
234 const char * const *attrs
= ac
->req
->op
.search
.attrs
;
235 const char **server_sasl
= NULL
;
236 const struct dsdb_schema
*schema
;
237 unsigned long long *val
;
238 struct ldb_control
*edn_control
;
239 const char *dn_attrs
[] = {
240 "configurationNamingContext",
241 "defaultNamingContext",
242 "rootDomainNamingContext",
243 "schemaNamingContext",
249 const char *guid_attrs
[] = {
255 ldb
= ldb_module_get_ctx(ac
->module
);
256 schema
= dsdb_get_schema(ldb
, NULL
);
258 msg
->dn
= ldb_dn_new(msg
, ldb
, NULL
);
260 /* don't return the distinguishedName, cn and name attributes */
261 ldb_msg_remove_attr(msg
, "distinguishedName");
262 ldb_msg_remove_attr(msg
, "cn");
263 ldb_msg_remove_attr(msg
, "name");
265 if (do_attribute(attrs
, "serverName")) {
266 if (ldb_msg_add_linearized_dn(msg
, "serverName",
267 samdb_server_dn(ldb
, msg
)) != LDB_SUCCESS
) {
272 if (do_attribute(attrs
, "dnsHostName")) {
273 struct ldb_result
*res
;
275 const char *dns_attrs
[] = { "dNSHostName", NULL
};
276 ret
= dsdb_module_search_dn(ac
->module
, msg
, &res
, samdb_server_dn(ldb
, msg
),
278 DSDB_FLAG_NEXT_MODULE
|
281 if (ret
== LDB_SUCCESS
) {
282 const char *hostname
= ldb_msg_find_attr_as_string(res
->msgs
[0], "dNSHostName", NULL
);
283 if (hostname
!= NULL
) {
284 if (ldb_msg_add_string(msg
, "dnsHostName", hostname
)) {
291 if (do_attribute(attrs
, "ldapServiceName")) {
292 struct loadparm_context
*lp_ctx
293 = talloc_get_type(ldb_get_opaque(ldb
, "loadparm"),
294 struct loadparm_context
);
295 char *ldap_service_name
, *hostname
;
297 hostname
= strlower_talloc(msg
, lpcfg_netbios_name(lp_ctx
));
298 if (hostname
== NULL
) {
302 ldap_service_name
= talloc_asprintf(msg
, "%s:%s$@%s",
303 samdb_forest_name(ldb
, msg
),
304 hostname
, lpcfg_realm(lp_ctx
));
305 if (ldap_service_name
== NULL
) {
309 if (ldb_msg_add_string(msg
, "ldapServiceName",
310 ldap_service_name
) != LDB_SUCCESS
) {
315 if (do_attribute(attrs
, "currentTime")) {
316 char *timestr
= ldb_timestring(msg
, time(NULL
));
318 if (timestr
== NULL
) {
322 if (ldb_msg_add_steal_string(
323 msg
, "currentTime", timestr
) != LDB_SUCCESS
) {
328 if (priv
&& do_attribute(attrs
, "supportedControl")) {
329 for (i
= 0; i
< priv
->num_controls
; i
++) {
330 char *control
= talloc_strdup(msg
, priv
->controls
[i
]);
334 if (ldb_msg_add_steal_string(msg
, "supportedControl",
335 control
) != LDB_SUCCESS
) {
341 if (priv
&& do_attribute(attrs
, "namingContexts")) {
342 for (i
= 0; i
< priv
->num_partitions
; i
++) {
343 struct ldb_dn
*dn
= priv
->partitions
[i
];
344 if (ldb_msg_add_steal_string(msg
, "namingContexts",
345 ldb_dn_alloc_linearized(msg
, dn
)) != LDB_SUCCESS
) {
351 server_sasl
= talloc_get_type(ldb_get_opaque(ldb
, "supportedSASLMechanisms"),
353 if (server_sasl
&& do_attribute(attrs
, "supportedSASLMechanisms")) {
354 for (i
= 0; server_sasl
&& server_sasl
[i
]; i
++) {
355 char *sasl_name
= talloc_strdup(msg
, server_sasl
[i
]);
359 if (ldb_msg_add_steal_string(msg
, "supportedSASLMechanisms",
360 sasl_name
) != LDB_SUCCESS
) {
366 if (do_attribute(attrs
, "highestCommittedUSN")) {
368 int ret
= ldb_sequence_number(ldb
, LDB_SEQ_HIGHEST_SEQ
, &seq_num
);
369 if (ret
== LDB_SUCCESS
) {
370 if (samdb_msg_add_uint64(ldb
, msg
, msg
,
371 "highestCommittedUSN",
372 seq_num
) != LDB_SUCCESS
) {
378 if (schema
&& do_attribute_explicit(attrs
, "dsSchemaAttrCount")) {
379 struct dsdb_attribute
*cur
;
382 for (cur
= schema
->attributes
; cur
; cur
= cur
->next
) {
386 if (samdb_msg_add_uint(ldb
, msg
, msg
, "dsSchemaAttrCount",
392 if (schema
&& do_attribute_explicit(attrs
, "dsSchemaClassCount")) {
393 struct dsdb_class
*cur
;
396 for (cur
= schema
->classes
; cur
; cur
= cur
->next
) {
400 if (samdb_msg_add_uint(ldb
, msg
, msg
, "dsSchemaClassCount",
406 if (schema
&& do_attribute_explicit(attrs
, "dsSchemaPrefixCount")) {
407 if (samdb_msg_add_uint(ldb
, msg
, msg
, "dsSchemaPrefixCount",
408 schema
->prefixmap
->length
) != LDB_SUCCESS
) {
413 if (do_attribute_explicit(attrs
, "validFSMOs")) {
414 struct ldb_dn
*dns
[3];
416 dns
[0] = ldb_get_schema_basedn(ldb
);
417 dns
[1] = samdb_partitions_dn(ldb
, msg
);
418 dns
[2] = ldb_get_default_basedn(ldb
);
420 for (i
=0; i
<3; i
++) {
422 int ret
= dsdb_module_we_are_master(ac
->module
, dns
[i
], &master
, ac
->req
);
423 if (ret
!= LDB_SUCCESS
) {
426 if (master
&& ldb_msg_add_fmt(msg
, "validFSMOs", "%s",
427 ldb_dn_get_linearized(dns
[i
])) != LDB_SUCCESS
) {
433 if (do_attribute_explicit(attrs
, "vendorVersion")) {
434 if (ldb_msg_add_fmt(msg
, "vendorVersion",
435 "%s", SAMBA_VERSION_STRING
) != LDB_SUCCESS
) {
440 if (do_attribute(attrs
, "domainFunctionality")) {
441 if (samdb_msg_add_int(ldb
, msg
, msg
, "domainFunctionality",
442 dsdb_functional_level(ldb
)) != LDB_SUCCESS
) {
447 if (do_attribute(attrs
, "forestFunctionality")) {
448 if (samdb_msg_add_int(ldb
, msg
, msg
, "forestFunctionality",
449 dsdb_forest_functional_level(ldb
)) != LDB_SUCCESS
) {
454 if (do_attribute(attrs
, "domainControllerFunctionality")
455 && (val
= talloc_get_type(ldb_get_opaque(ldb
, "domainControllerFunctionality"), unsigned long long))) {
456 if (samdb_msg_add_int(ldb
, msg
, msg
,
457 "domainControllerFunctionality",
458 *val
) != LDB_SUCCESS
) {
463 if (do_attribute(attrs
, "isGlobalCatalogReady")) {
464 /* MS-ADTS 3.1.1.3.2.10
465 Note, we should only return true here is we have
466 completed at least one synchronisation. As both
467 provision and vampire do a full sync, this means we
468 can return true is the gc bit is set in the NTDSDSA
470 if (ldb_msg_add_fmt(msg
, "isGlobalCatalogReady",
471 "%s", samdb_is_gc(ldb
)?"TRUE":"FALSE") != LDB_SUCCESS
) {
476 if (do_attribute_explicit(attrs
, "tokenGroups")) {
477 /* Obtain the user's session_info */
478 struct auth_session_info
*session_info
479 = (struct auth_session_info
*)ldb_get_opaque(
482 if (session_info
&& session_info
->security_token
) {
483 /* The list of groups this user is in */
484 for (i
= 0; i
< session_info
->security_token
->num_sids
; i
++) {
485 if (samdb_msg_add_dom_sid(ldb
, msg
, msg
,
487 &session_info
->security_token
->sids
[i
]) != LDB_SUCCESS
) {
494 if (ac
->netlogon
.length
> 0) {
495 if (ldb_msg_add_steal_value(msg
, "netlogon", &ac
->netlogon
) != LDB_SUCCESS
) {
500 /* TODO: lots more dynamic attributes should be added here */
502 edn_control
= ldb_request_get_control(ac
->req
, LDB_CONTROL_EXTENDED_DN_OID
);
504 /* convert any GUID attributes to be in the right form */
505 for (i
=0; guid_attrs
[i
]; i
++) {
506 struct ldb_result
*res
;
507 struct ldb_message_element
*el
;
508 struct ldb_dn
*attr_dn
;
509 const char *no_attrs
[] = { NULL
};
512 if (!do_attribute(attrs
, guid_attrs
[i
])) continue;
514 attr_dn
= ldb_msg_find_attr_as_dn(ldb
, ac
->req
, msg
, guid_attrs
[i
]);
515 if (attr_dn
== NULL
) {
519 ret
= dsdb_module_search_dn(ac
->module
, ac
->req
, &res
,
521 DSDB_FLAG_NEXT_MODULE
|
522 DSDB_FLAG_AS_SYSTEM
|
523 DSDB_SEARCH_SHOW_EXTENDED_DN
,
525 if (ret
!= LDB_SUCCESS
) {
526 DBG_WARNING("Failed to convert GUID into full DN in rootDSE for %s: %s: %s\n",
528 ldb_dn_get_extended_linearized(ac
, attr_dn
, 1),
531 * Provide a meaningful error string but not
532 * confidential DB contents possibly in the
535 ldb_asprintf_errstring(ldb
,
536 "Failed to find full DN for %s: %s",
538 ldb_dn_get_extended_linearized(ac
, attr_dn
, 1));
539 /* Overstamp the error code, it would confuse the caller */
540 return LDB_ERR_OPERATIONS_ERROR
;
543 el
= ldb_msg_find_element(msg
, guid_attrs
[i
]);
545 return ldb_operr(ldb
);
548 talloc_steal(el
->values
, res
->msgs
[0]->dn
);
550 struct ldb_extended_dn_control
*ext_dn
;
552 ext_dn
= talloc_get_type(edn_control
->data
, struct ldb_extended_dn_control
);
553 if (ext_dn
!= NULL
) {
554 edn_type
= ext_dn
->type
;
556 el
->values
[0].data
= (uint8_t *)ldb_dn_get_extended_linearized(el
->values
,
560 el
->values
[0].data
= (uint8_t *)talloc_strdup(el
->values
,
561 ldb_dn_get_linearized(res
->msgs
[0]->dn
));
563 if (el
->values
[0].data
== NULL
) {
566 el
->values
[0].length
= strlen((const char *)el
->values
[0].data
);
569 /* if the client sent us the EXTENDED_DN control then we need
570 to expand the DNs to have GUID and SID. W2K8 join relies on
574 for (i
=0; dn_attrs
[i
]; i
++) {
575 if (!do_attribute(attrs
, dn_attrs
[i
])) continue;
576 ret
= expand_dn_in_message(ac
->module
, msg
, dn_attrs
[i
],
577 edn_control
, ac
->req
);
578 if (ret
!= LDB_SUCCESS
) {
579 DEBUG(0,(__location__
": Failed to expand DN in rootDSE for %s\n",
589 return ldb_operr(ldb
);
593 handle search requests
596 static struct rootdse_context
*rootdse_init_context(struct ldb_module
*module
,
597 struct ldb_request
*req
)
599 struct ldb_context
*ldb
;
600 struct rootdse_context
*ac
;
602 ldb
= ldb_module_get_ctx(module
);
604 ac
= talloc_zero(req
, struct rootdse_context
);
606 ldb_set_errstring(ldb
, "Out of Memory");
616 static int rootdse_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
618 struct rootdse_context
*ac
;
621 ac
= talloc_get_type(req
->context
, struct rootdse_context
);
624 return ldb_module_done(ac
->req
, NULL
, NULL
,
625 LDB_ERR_OPERATIONS_ERROR
);
627 if (ares
->error
!= LDB_SUCCESS
) {
628 return ldb_module_done(ac
->req
, ares
->controls
,
629 ares
->response
, ares
->error
);
632 switch (ares
->type
) {
633 case LDB_REPLY_ENTRY
:
634 /* for each record returned post-process to add any dynamic
635 attributes that have been asked for */
636 ret
= rootdse_add_dynamic(ac
, ares
->message
);
637 if (ret
!= LDB_SUCCESS
) {
639 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
642 return ldb_module_send_entry(ac
->req
, ares
->message
, ares
->controls
);
644 case LDB_REPLY_REFERRAL
:
645 /* should we allow the backend to return referrals in this case
650 return ldb_module_done(ac
->req
, ares
->controls
,
651 ares
->response
, ares
->error
);
659 filter from controls from clients in several ways
661 1) mark our registered controls as non-critical in the request
663 This is needed as clients may mark controls as critical even if
664 they are not needed at all in a request. For example, the centrify
665 client sets the SD_FLAGS control as critical on ldap modify
666 requests which are setting the dNSHostName attribute on the
667 machine account. That request doesn't need SD_FLAGS at all, but
668 centrify adds it on all ldap requests.
670 2) if this request is untrusted then remove any non-registered
671 controls that are non-critical
673 This is used on ldap:// connections to prevent remote users from
674 setting an internal control that may be dangerous
676 3) if this request is untrusted then fail any request that includes
677 a critical non-registered control
679 static int rootdse_filter_controls(struct ldb_module
*module
, struct ldb_request
*req
)
682 struct rootdse_private_data
*priv
= talloc_get_type(ldb_module_get_private(module
), struct rootdse_private_data
);
685 if (!req
->controls
) {
689 is_untrusted
= ldb_req_is_untrusted(req
);
691 for (i
=0; req
->controls
[i
]; i
++) {
692 bool is_registered
= false;
693 bool is_critical
= (req
->controls
[i
]->critical
!= 0);
695 if (req
->controls
[i
]->oid
== NULL
) {
699 if (is_untrusted
|| is_critical
) {
700 for (j
=0; j
<priv
->num_controls
; j
++) {
701 if (strcasecmp(priv
->controls
[j
], req
->controls
[i
]->oid
) == 0) {
702 is_registered
= true;
708 if (is_untrusted
&& !is_registered
) {
710 /* remove it by marking the oid NULL */
711 req
->controls
[i
]->oid
= NULL
;
712 req
->controls
[i
]->data
= NULL
;
713 req
->controls
[i
]->critical
= 0;
716 /* its a critical unregistered control - give
718 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
719 "Attempt to use critical non-registered control '%s'",
720 req
->controls
[i
]->oid
);
721 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION
;
729 * If the control is DIRSYNC, SORT or VLV then we keep the
730 * critical flag as the modules will need to act upon it.
732 * These modules have to unset the critical flag after the
733 * request has been seen by the correct module.
736 strcmp(req
->controls
[i
]->oid
,
737 LDB_CONTROL_DIRSYNC_OID
) != 0 &&
738 strcmp(req
->controls
[i
]->oid
,
739 LDB_CONTROL_VLV_REQ_OID
) != 0 &&
740 strcmp(req
->controls
[i
]->oid
,
741 LDB_CONTROL_SERVER_SORT_OID
) != 0) {
742 req
->controls
[i
]->critical
= 0;
749 /* Ensure that anonymous users are not allowed to make anything other than rootDSE search operations */
751 static int rootdse_filter_operations(struct ldb_module
*module
, struct ldb_request
*req
)
753 struct auth_session_info
*session_info
;
754 struct rootdse_private_data
*priv
= talloc_get_type(ldb_module_get_private(module
), struct rootdse_private_data
);
755 bool is_untrusted
= ldb_req_is_untrusted(req
);
756 bool is_anonymous
= true;
757 if (is_untrusted
== false) {
761 session_info
= (struct auth_session_info
*)ldb_get_opaque(
762 ldb_module_get_ctx(module
),
765 is_anonymous
= security_token_is_anonymous(session_info
->security_token
);
768 if (is_anonymous
== false || (priv
&& priv
->block_anonymous
== false)) {
772 if (req
->operation
== LDB_SEARCH
) {
773 if (req
->op
.search
.scope
== LDB_SCOPE_BASE
&& ldb_dn_is_null(req
->op
.search
.base
)) {
777 ldb_set_errstring(ldb_module_get_ctx(module
), "Operation unavailable without authentication");
778 return LDB_ERR_OPERATIONS_ERROR
;
781 static int rootdse_handle_netlogon(struct rootdse_context
*ac
)
783 struct ldb_context
*ldb
;
784 struct ldb_parse_tree
*tree
;
785 struct loadparm_context
*lp_ctx
;
786 struct tsocket_address
*src_addr
;
787 TALLOC_CTX
*tmp_ctx
= talloc_new(ac
->req
);
788 const char *domain
, *host
, *user
, *domain_guid
;
789 char *src_addr_s
= NULL
;
790 struct dom_sid
*domain_sid
;
791 int acct_control
= -1;
794 struct netlogon_samlogon_response netlogon
;
795 int ret
= LDB_ERR_OPERATIONS_ERROR
;
797 ldb
= ldb_module_get_ctx(ac
->module
);
798 tree
= ac
->req
->op
.search
.tree
;
799 lp_ctx
= talloc_get_type(ldb_get_opaque(ldb
, "loadparm"),
800 struct loadparm_context
);
801 src_addr
= talloc_get_type(ldb_get_opaque(ldb
, "remoteAddress"),
802 struct tsocket_address
);
804 src_addr_s
= tsocket_address_inet_addr_string(src_addr
,
808 status
= parse_netlogon_request(tree
, lp_ctx
, tmp_ctx
,
809 &domain
, &host
, &user
, &domain_guid
,
810 &domain_sid
, &acct_control
, &version
);
811 if (!NT_STATUS_IS_OK(status
)) {
815 status
= fill_netlogon_samlogon_response(ldb
, tmp_ctx
,
816 domain
, NULL
, domain_sid
,
822 if (!NT_STATUS_IS_OK(status
)) {
826 status
= push_netlogon_samlogon_response(&ac
->netlogon
, ac
, &netlogon
);
827 if (!NT_STATUS_IS_OK(status
)) {
833 talloc_free(tmp_ctx
);
837 static int rootdse_search(struct ldb_module
*module
, struct ldb_request
*req
)
839 struct ldb_context
*ldb
;
840 struct rootdse_context
*ac
;
841 struct ldb_request
*down_req
;
844 ret
= rootdse_filter_operations(module
, req
);
845 if (ret
!= LDB_SUCCESS
) {
849 ret
= rootdse_filter_controls(module
, req
);
850 if (ret
!= LDB_SUCCESS
) {
854 ldb
= ldb_module_get_ctx(module
);
856 /* see if its for the rootDSE - only a base search on the "" DN qualifies */
857 if (!(req
->op
.search
.scope
== LDB_SCOPE_BASE
&& ldb_dn_is_null(req
->op
.search
.base
))) {
858 /* Otherwise, pass down to the rest of the stack */
859 return ldb_next_request(module
, req
);
862 ac
= rootdse_init_context(module
, req
);
864 return ldb_operr(ldb
);
867 if (do_attribute_explicit(req
->op
.search
.attrs
, "netlogon")) {
868 ret
= rootdse_handle_netlogon(ac
);
869 /* We have to return an empty result, so don't forward `ret' */
870 if (ret
!= LDB_SUCCESS
) {
871 return ldb_module_done(ac
->req
, NULL
, NULL
, LDB_SUCCESS
);
875 /* in our db we store the rootDSE with a DN of @ROOTDSE */
876 ret
= ldb_build_search_req(&down_req
, ldb
, ac
,
877 ldb_dn_new(ac
, ldb
, "@ROOTDSE"),
880 req
->op
.search
.attrs
,
881 NULL
,/* for now skip the controls from the client */
882 ac
, rootdse_callback
,
884 LDB_REQ_SET_LOCATION(down_req
);
885 if (ret
!= LDB_SUCCESS
) {
889 return ldb_next_request(module
, down_req
);
892 static struct rootdse_private_data
*rootdse_get_private_data(struct ldb_module
*module
)
894 void *priv
= ldb_module_get_private(module
);
895 struct rootdse_private_data
*data
= NULL
;
896 struct ldb_context
*ldb
897 = ldb_module_get_ctx(module
);
900 data
= talloc_get_type_abort(priv
,
901 struct rootdse_private_data
);
908 data
= talloc_zero(module
, struct rootdse_private_data
);
913 data
->num_controls
= 0;
914 data
->controls
= NULL
;
915 data
->num_partitions
= 0;
916 data
->partitions
= NULL
;
917 data
->block_anonymous
= true;
919 ldb_module_set_private(module
, data
);
921 ldb_set_default_dns(ldb
);
927 static int rootdse_register_control(struct ldb_module
*module
, struct ldb_request
*req
)
929 struct rootdse_private_data
*priv
=
930 rootdse_get_private_data(module
);
934 return ldb_module_oom(module
);
937 list
= talloc_realloc(priv
, priv
->controls
, char *, priv
->num_controls
+ 1);
939 return ldb_oom(ldb_module_get_ctx(module
));
942 list
[priv
->num_controls
] = talloc_strdup(list
, req
->op
.reg_control
.oid
);
943 if (!list
[priv
->num_controls
]) {
944 return ldb_oom(ldb_module_get_ctx(module
));
947 priv
->num_controls
+= 1;
948 priv
->controls
= list
;
950 return ldb_module_done(req
, NULL
, NULL
, LDB_SUCCESS
);
953 static int rootdse_register_partition(struct ldb_module
*module
, struct ldb_request
*req
)
955 struct rootdse_private_data
*priv
=
956 rootdse_get_private_data(module
);
957 struct ldb_dn
**list
;
960 return ldb_module_oom(module
);
963 list
= talloc_realloc(priv
, priv
->partitions
, struct ldb_dn
*, priv
->num_partitions
+ 1);
965 return ldb_oom(ldb_module_get_ctx(module
));
968 list
[priv
->num_partitions
] = ldb_dn_copy(list
, req
->op
.reg_partition
.dn
);
969 if (!list
[priv
->num_partitions
]) {
970 return ldb_operr(ldb_module_get_ctx(module
));
973 priv
->num_partitions
+= 1;
974 priv
->partitions
= list
;
976 return ldb_module_done(req
, NULL
, NULL
, LDB_SUCCESS
);
980 static int rootdse_request(struct ldb_module
*module
, struct ldb_request
*req
)
982 switch (req
->operation
) {
984 case LDB_REQ_REGISTER_CONTROL
:
985 return rootdse_register_control(module
, req
);
986 case LDB_REQ_REGISTER_PARTITION
:
987 return rootdse_register_partition(module
, req
);
992 return ldb_next_request(module
, req
);
995 static int rootdse_init(struct ldb_module
*module
)
998 struct ldb_result
*res
;
999 const char *attrs
[] = { "msDS-Behavior-Version", NULL
};
1000 const char *ds_attrs
[] = { "dsServiceName", NULL
};
1001 TALLOC_CTX
*mem_ctx
;
1003 struct ldb_context
*ldb
1004 = ldb_module_get_ctx(module
);
1006 struct rootdse_private_data
*data
1007 = rootdse_get_private_data(module
);
1010 return ldb_module_oom(module
);
1013 ret
= ldb_next_init(module
);
1015 if (ret
!= LDB_SUCCESS
) {
1019 mem_ctx
= talloc_new(data
);
1021 return ldb_oom(ldb
);
1024 /* Now that the partitions are set up, do a search for:
1025 - domainControllerFunctionality
1026 - domainFunctionality
1027 - forestFunctionality
1029 Then stuff these values into an opaque
1031 ret
= dsdb_module_search(module
, mem_ctx
, &res
,
1032 ldb_get_default_basedn(ldb
),
1033 LDB_SCOPE_BASE
, attrs
,
1034 DSDB_FLAG_NEXT_MODULE
|
1035 DSDB_FLAG_AS_SYSTEM
,
1037 if (ret
== LDB_SUCCESS
&& res
->count
== 1) {
1038 int domain_behaviour_version
1039 = ldb_msg_find_attr_as_int(res
->msgs
[0],
1040 "msDS-Behavior-Version", -1);
1041 if (domain_behaviour_version
!= -1) {
1042 unsigned long long *val
1043 = talloc(ldb
, unsigned long long);
1045 talloc_free(mem_ctx
);
1046 return ldb_oom(ldb
);
1048 *val
= domain_behaviour_version
;
1049 ret
= ldb_set_opaque(ldb
, "domainFunctionality", val
);
1050 if (ret
!= LDB_SUCCESS
) {
1051 talloc_free(mem_ctx
);
1057 ret
= dsdb_module_search(module
, mem_ctx
, &res
,
1058 samdb_partitions_dn(ldb
, mem_ctx
),
1059 LDB_SCOPE_BASE
, attrs
,
1060 DSDB_FLAG_NEXT_MODULE
|
1061 DSDB_FLAG_AS_SYSTEM
,
1063 if (ret
== LDB_SUCCESS
&& res
->count
== 1) {
1064 int forest_behaviour_version
1065 = ldb_msg_find_attr_as_int(res
->msgs
[0],
1066 "msDS-Behavior-Version", -1);
1067 if (forest_behaviour_version
!= -1) {
1068 unsigned long long *val
1069 = talloc(ldb
, unsigned long long);
1071 talloc_free(mem_ctx
);
1072 return ldb_oom(ldb
);
1074 *val
= forest_behaviour_version
;
1075 ret
= ldb_set_opaque(ldb
, "forestFunctionality", val
);
1076 if (ret
!= LDB_SUCCESS
) {
1077 talloc_free(mem_ctx
);
1085 * For now, our own server's location in the DB is recorded in
1086 * the @ROOTDSE record
1088 * We can't call samdb_ntds_settings_dn() in the rootdse, as
1089 * that routine used the rootdse result!
1091 ret
= dsdb_module_search(module
, mem_ctx
, &res
,
1092 ldb_dn_new(mem_ctx
, ldb
, "@ROOTDSE"),
1093 LDB_SCOPE_BASE
, ds_attrs
,
1094 DSDB_FLAG_NEXT_MODULE
|
1095 DSDB_FLAG_AS_SYSTEM
,
1097 if (ret
== LDB_SUCCESS
&& res
->count
== 1) {
1098 struct ldb_dn
*ds_dn
1099 = ldb_msg_find_attr_as_dn(ldb
, mem_ctx
, res
->msgs
[0],
1102 ret
= dsdb_module_search(module
, mem_ctx
, &res
, ds_dn
,
1103 LDB_SCOPE_BASE
, attrs
,
1104 DSDB_FLAG_NEXT_MODULE
|
1105 DSDB_FLAG_AS_SYSTEM
,
1107 if (ret
== LDB_SUCCESS
&& res
->count
== 1) {
1108 int domain_controller_behaviour_version
1109 = ldb_msg_find_attr_as_int(res
->msgs
[0],
1110 "msDS-Behavior-Version", -1);
1111 if (domain_controller_behaviour_version
!= -1) {
1112 unsigned long long *val
1113 = talloc(ldb
, unsigned long long);
1115 talloc_free(mem_ctx
);
1116 return ldb_oom(ldb
);
1118 *val
= domain_controller_behaviour_version
;
1119 ret
= ldb_set_opaque(ldb
,
1120 "domainControllerFunctionality", val
);
1121 if (ret
!= LDB_SUCCESS
) {
1122 talloc_free(mem_ctx
);
1130 data
->block_anonymous
= dsdb_block_anonymous_ops(module
, NULL
);
1132 talloc_free(mem_ctx
);
1138 * This function gets the string SCOPE_DN:OPTIONAL_FEATURE_GUID and parse it
1139 * to a DN and a GUID object
1141 static int get_optional_feature_dn_guid(struct ldb_request
*req
, struct ldb_context
*ldb
,
1142 TALLOC_CTX
*mem_ctx
,
1143 struct ldb_dn
**op_feature_scope_dn
,
1144 struct GUID
*op_feature_guid
)
1146 const struct ldb_message
*msg
= req
->op
.mod
.message
;
1147 const char *ldb_val_str
;
1149 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
1152 ldb_val_str
= ldb_msg_find_attr_as_string(msg
, "enableOptionalFeature", NULL
);
1154 ldb_set_errstring(ldb
,
1155 "rootdse: unable to find 'enableOptionalFeature'!");
1156 return LDB_ERR_UNWILLING_TO_PERFORM
;
1159 guid
= strchr(ldb_val_str
, ':');
1161 ldb_set_errstring(ldb
,
1162 "rootdse: unable to find GUID in 'enableOptionalFeature'!");
1163 return LDB_ERR_UNWILLING_TO_PERFORM
;
1165 status
= GUID_from_string(guid
+1, op_feature_guid
);
1166 if (!NT_STATUS_IS_OK(status
)) {
1167 ldb_set_errstring(ldb
,
1168 "rootdse: bad GUID in 'enableOptionalFeature'!");
1169 return LDB_ERR_UNWILLING_TO_PERFORM
;
1172 dn
= talloc_strndup(tmp_ctx
, ldb_val_str
, guid
-ldb_val_str
);
1174 ldb_set_errstring(ldb
,
1175 "rootdse: bad DN in 'enableOptionalFeature'!");
1176 return LDB_ERR_UNWILLING_TO_PERFORM
;
1179 *op_feature_scope_dn
= ldb_dn_new(mem_ctx
, ldb
, dn
);
1181 talloc_free(tmp_ctx
);
1186 * This function gets the OPTIONAL_FEATURE_GUID and looks for the optional feature
1187 * ldb_message object.
1189 static int dsdb_find_optional_feature(struct ldb_module
*module
, struct ldb_context
*ldb
,
1190 TALLOC_CTX
*mem_ctx
, struct GUID op_feature_guid
, struct ldb_message
**msg
,
1191 struct ldb_request
*parent
)
1193 struct ldb_result
*res
;
1194 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
1197 ret
= dsdb_module_search(module
, tmp_ctx
, &res
, NULL
, LDB_SCOPE_SUBTREE
,
1199 DSDB_FLAG_NEXT_MODULE
|
1200 DSDB_FLAG_AS_SYSTEM
|
1201 DSDB_SEARCH_SEARCH_ALL_PARTITIONS
,
1203 "(&(objectClass=msDS-OptionalFeature)"
1204 "(msDS-OptionalFeatureGUID=%s))",GUID_string(tmp_ctx
, &op_feature_guid
));
1206 if (ret
!= LDB_SUCCESS
) {
1207 talloc_free(tmp_ctx
);
1210 if (res
->count
== 0) {
1211 talloc_free(tmp_ctx
);
1212 return LDB_ERR_NO_SUCH_OBJECT
;
1214 if (res
->count
!= 1) {
1215 ldb_asprintf_errstring(ldb
,
1216 "More than one object found matching optional feature GUID %s\n",
1217 GUID_string(tmp_ctx
, &op_feature_guid
));
1218 talloc_free(tmp_ctx
);
1219 return LDB_ERR_OPERATIONS_ERROR
;
1222 *msg
= talloc_steal(mem_ctx
, res
->msgs
[0]);
1224 talloc_free(tmp_ctx
);
1228 static int rootdse_enable_recycle_bin(struct ldb_module
*module
,struct ldb_context
*ldb
,
1229 TALLOC_CTX
*mem_ctx
, struct ldb_dn
*op_feature_scope_dn
,
1230 struct ldb_message
*op_feature_msg
, struct ldb_request
*parent
)
1233 const int domain_func_level
= dsdb_functional_level(ldb
);
1234 struct ldb_dn
*ntds_settings_dn
;
1235 TALLOC_CTX
*tmp_ctx
;
1236 unsigned int el_count
= 0;
1237 struct ldb_message
*msg
;
1239 ret
= ldb_msg_find_attr_as_int(op_feature_msg
, "msDS-RequiredForestBehaviorVersion", 0);
1240 if (domain_func_level
< ret
){
1241 ldb_asprintf_errstring(ldb
,
1242 "rootdse_enable_recycle_bin: Domain functional level must be at least %d\n",
1244 return LDB_ERR_UNWILLING_TO_PERFORM
;
1247 tmp_ctx
= talloc_new(mem_ctx
);
1248 ntds_settings_dn
= samdb_ntds_settings_dn(ldb
, tmp_ctx
);
1249 if (!ntds_settings_dn
) {
1250 talloc_free(tmp_ctx
);
1251 return ldb_error(ldb
, LDB_ERR_OPERATIONS_ERROR
, "Failed to find NTDS settings DN");
1254 ntds_settings_dn
= ldb_dn_copy(tmp_ctx
, ntds_settings_dn
);
1255 if (!ntds_settings_dn
) {
1256 talloc_free(tmp_ctx
);
1257 return ldb_error(ldb
, LDB_ERR_OPERATIONS_ERROR
, "Failed to copy NTDS settings DN");
1260 msg
= ldb_msg_new(tmp_ctx
);
1262 talloc_free(tmp_ctx
);
1263 return ldb_module_oom(module
);
1265 msg
->dn
= ntds_settings_dn
;
1267 ldb_msg_add_linearized_dn(msg
, "msDS-EnabledFeature", op_feature_msg
->dn
);
1268 msg
->elements
[el_count
++].flags
= LDB_FLAG_MOD_ADD
;
1270 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
, parent
);
1271 if (ret
!= LDB_SUCCESS
) {
1272 ldb_asprintf_errstring(ldb
,
1273 "rootdse_enable_recycle_bin: Failed to modify object %s - %s",
1274 ldb_dn_get_linearized(ntds_settings_dn
),
1275 ldb_errstring(ldb
));
1276 talloc_free(tmp_ctx
);
1280 msg
->dn
= op_feature_scope_dn
;
1281 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
, parent
);
1282 if (ret
!= LDB_SUCCESS
) {
1283 ldb_asprintf_errstring(ldb
,
1284 "rootdse_enable_recycle_bin: Failed to modify object %s - %s",
1285 ldb_dn_get_linearized(op_feature_scope_dn
),
1286 ldb_errstring(ldb
));
1287 talloc_free(tmp_ctx
);
1294 static int rootdse_enableoptionalfeature(struct ldb_module
*module
, struct ldb_request
*req
)
1298 - check for system (only system can enable features)
1299 - extract GUID from the request
1300 - find the feature object
1301 - check functional level, must be at least msDS-RequiredForestBehaviorVersion
1302 - check if it is already enabled (if enabled return LDAP_ATTRIBUTE_OR_VALUE_EXISTS) - probably not needed, just return error from the add/modify
1303 - add/modify objects (see ntdsconnection code for an example)
1306 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1307 struct GUID op_feature_guid
;
1308 struct ldb_dn
*op_feature_scope_dn
;
1309 struct ldb_message
*op_feature_msg
;
1310 struct auth_session_info
*session_info
=
1311 (struct auth_session_info
*)ldb_get_opaque(
1314 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
1316 const char *guid_string
;
1318 if (security_session_user_level(session_info
, NULL
) != SECURITY_SYSTEM
) {
1319 ldb_set_errstring(ldb
, "rootdse: Insufficient rights for enableoptionalfeature");
1320 return LDB_ERR_UNWILLING_TO_PERFORM
;
1323 ret
= get_optional_feature_dn_guid(req
, ldb
, tmp_ctx
, &op_feature_scope_dn
, &op_feature_guid
);
1324 if (ret
!= LDB_SUCCESS
) {
1325 talloc_free(tmp_ctx
);
1329 guid_string
= GUID_string(tmp_ctx
, &op_feature_guid
);
1331 ldb_set_errstring(ldb
, "rootdse: bad optional feature GUID");
1332 return LDB_ERR_UNWILLING_TO_PERFORM
;
1335 ret
= dsdb_find_optional_feature(module
, ldb
, tmp_ctx
, op_feature_guid
, &op_feature_msg
, req
);
1336 if (ret
!= LDB_SUCCESS
) {
1337 ldb_asprintf_errstring(ldb
,
1338 "rootdse: unable to find optional feature for %s - %s",
1339 guid_string
, ldb_errstring(ldb
));
1340 talloc_free(tmp_ctx
);
1344 if (strcasecmp(DS_GUID_FEATURE_RECYCLE_BIN
, guid_string
) == 0) {
1345 ret
= rootdse_enable_recycle_bin(module
, ldb
,
1346 tmp_ctx
, op_feature_scope_dn
,
1347 op_feature_msg
, req
);
1349 ldb_asprintf_errstring(ldb
,
1350 "rootdse: unknown optional feature %s",
1352 talloc_free(tmp_ctx
);
1353 return LDB_ERR_UNWILLING_TO_PERFORM
;
1355 if (ret
!= LDB_SUCCESS
) {
1356 ldb_asprintf_errstring(ldb
,
1357 "rootdse: failed to set optional feature for %s - %s",
1358 guid_string
, ldb_errstring(ldb
));
1359 talloc_free(tmp_ctx
);
1363 talloc_free(tmp_ctx
);
1364 return ldb_module_done(req
, NULL
, NULL
, LDB_SUCCESS
);;
1367 static int rootdse_schemaupdatenow(struct ldb_module
*module
, struct ldb_request
*req
)
1369 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1370 struct ldb_result
*ext_res
;
1372 struct ldb_dn
*schema_dn
;
1374 schema_dn
= ldb_get_schema_basedn(ldb
);
1376 ldb_reset_err_string(ldb
);
1377 ldb_debug(ldb
, LDB_DEBUG_WARNING
,
1378 "rootdse_modify: no schema dn present: (skip ldb_extended call)\n");
1379 return ldb_next_request(module
, req
);
1383 * schemaUpdateNow has been requested. Allow this to refresh the schema
1384 * even if we're currently in the middle of a transaction
1386 ret
= ldb_set_opaque(ldb
, "dsdb_schema_refresh_expected", (void *)1);
1387 if (ret
!= LDB_SUCCESS
) {
1388 return ldb_operr(ldb
);
1391 ret
= ldb_extended(ldb
, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID
, schema_dn
, &ext_res
);
1392 if (ret
!= LDB_SUCCESS
) {
1393 ldb_set_opaque(ldb
, "dsdb_schema_refresh_expected", (void *)0);
1394 return ldb_operr(ldb
);
1397 talloc_free(ext_res
);
1399 ret
= ldb_set_opaque(ldb
, "dsdb_schema_refresh_expected", (void *)0);
1400 if (ret
!= LDB_SUCCESS
) {
1401 return ldb_operr(ldb
);
1404 return ldb_module_done(req
, NULL
, NULL
, ret
);
1407 static int rootdse_schemaupgradeinprogress(struct ldb_module
*module
, struct ldb_request
*req
)
1409 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1410 int ret
= LDB_SUCCESS
;
1411 struct ldb_dn
*schema_dn
;
1413 schema_dn
= ldb_get_schema_basedn(ldb
);
1415 ldb_reset_err_string(ldb
);
1416 ldb_debug(ldb
, LDB_DEBUG_WARNING
,
1417 "rootdse_modify: no schema dn present: (skip ldb_extended call)\n");
1418 return ldb_next_request(module
, req
);
1421 /* FIXME we have to do something in order to relax constraints for DRS
1422 * setting schemaUpgradeInProgress cause the fschemaUpgradeInProgress
1423 * in all LDAP connection (2K3/2K3R2) or in the current connection (2K8 and +)
1424 * to be set to true.
1427 /* from 5.113 LDAPConnections in DRSR.pdf
1428 * fschemaUpgradeInProgress: A Boolean that specifies certain constraint
1429 * validations are skipped when adding, updating, or removing directory
1430 * objects on the opened connection. The skipped constraint validations
1431 * are documented in the applicable constraint sections in [MS-ADTS].
1433 return ldb_module_done(req
, NULL
, NULL
, ret
);
1436 static int rootdse_add(struct ldb_module
*module
, struct ldb_request
*req
)
1438 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1441 ret
= rootdse_filter_operations(module
, req
);
1442 if (ret
!= LDB_SUCCESS
) {
1446 ret
= rootdse_filter_controls(module
, req
);
1447 if (ret
!= LDB_SUCCESS
) {
1452 If dn is not "" we should let it pass through
1454 if (!ldb_dn_is_null(req
->op
.add
.message
->dn
)) {
1455 return ldb_next_request(module
, req
);
1458 ldb_set_errstring(ldb
, "rootdse_add: you cannot add a new rootdse entry!");
1459 return LDB_ERR_NAMING_VIOLATION
;
1462 static int rootdse_start_trans(struct ldb_module
*module
)
1465 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1466 struct rootdse_private_data
*data
= talloc_get_type_abort(ldb_module_get_private(module
),
1467 struct rootdse_private_data
);
1468 ret
= ldb_next_start_trans(module
);
1469 if (ret
== LDB_SUCCESS
) {
1470 if (data
->private_ev
!= NULL
) {
1471 return ldb_operr(ldb
);
1473 data
->private_ev
= s4_event_context_init(data
);
1474 if (data
->private_ev
== NULL
) {
1475 return ldb_operr(ldb
);
1477 data
->saved_ev
= ldb_get_event_context(ldb
);
1478 ldb_set_event_context(ldb
, data
->private_ev
);
1483 static int rootdse_end_trans(struct ldb_module
*module
)
1486 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1487 struct rootdse_private_data
*data
= talloc_get_type_abort(ldb_module_get_private(module
),
1488 struct rootdse_private_data
);
1489 ret
= ldb_next_end_trans(module
);
1490 if (data
->saved_ev
== NULL
) {
1491 return ldb_operr(ldb
);
1494 if (data
->private_ev
!= ldb_get_event_context(ldb
)) {
1495 return ldb_operr(ldb
);
1497 ldb_set_event_context(ldb
, data
->saved_ev
);
1498 data
->saved_ev
= NULL
;
1499 TALLOC_FREE(data
->private_ev
);
1503 static int rootdse_del_trans(struct ldb_module
*module
)
1506 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1507 struct rootdse_private_data
*data
= talloc_get_type_abort(ldb_module_get_private(module
),
1508 struct rootdse_private_data
);
1509 ret
= ldb_next_del_trans(module
);
1510 if (data
->saved_ev
== NULL
) {
1511 return ldb_operr(ldb
);
1514 if (data
->private_ev
!= ldb_get_event_context(ldb
)) {
1515 return ldb_operr(ldb
);
1517 ldb_set_event_context(ldb
, data
->saved_ev
);
1518 data
->saved_ev
= NULL
;
1519 TALLOC_FREE(data
->private_ev
);
1523 struct fsmo_transfer_state
{
1524 struct ldb_context
*ldb
;
1525 struct ldb_request
*req
;
1526 struct ldb_module
*module
;
1530 called when a FSMO transfer operation has completed
1532 static void rootdse_fsmo_transfer_callback(struct tevent_req
*treq
)
1534 struct fsmo_transfer_state
*fsmo
= tevent_req_callback_data(treq
, struct fsmo_transfer_state
);
1538 struct ldb_request
*req
= fsmo
->req
;
1539 struct ldb_context
*ldb
= fsmo
->ldb
;
1540 struct ldb_module
*module
= fsmo
->module
;
1542 status
= dcerpc_drepl_takeFSMORole_recv(treq
, fsmo
, &werr
);
1544 if (!NT_STATUS_IS_OK(status
)) {
1545 ldb_asprintf_errstring(ldb
, "Failed FSMO transfer: %s", nt_errstr(status
));
1547 * Now that it is failed, start the transaction up
1548 * again so the wrappers can close it without additional error
1550 rootdse_start_trans(module
);
1551 ldb_module_done(req
, NULL
, NULL
, LDB_ERR_UNAVAILABLE
);
1554 if (!W_ERROR_IS_OK(werr
)) {
1555 ldb_asprintf_errstring(ldb
, "Failed FSMO transfer: %s", win_errstr(werr
));
1557 * Now that it is failed, start the transaction up
1558 * again so the wrappers can close it without additional error
1560 rootdse_start_trans(module
);
1561 ldb_module_done(req
, NULL
, NULL
, LDB_ERR_UNAVAILABLE
);
1566 * Now that it is done, start the transaction up again so the
1567 * wrappers can close it without error
1569 ret
= rootdse_start_trans(module
);
1570 ldb_module_done(req
, NULL
, NULL
, ret
);
1573 static int rootdse_become_master(struct ldb_module
*module
,
1574 struct ldb_request
*req
,
1575 enum drepl_role_master role
)
1577 struct imessaging_context
*msg
;
1578 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1579 TALLOC_CTX
*tmp_ctx
= talloc_new(req
);
1580 struct loadparm_context
*lp_ctx
= ldb_get_opaque(ldb
, "loadparm");
1582 struct dcerpc_binding_handle
*irpc_handle
;
1584 struct auth_session_info
*session_info
;
1585 enum security_user_level level
;
1586 struct fsmo_transfer_state
*fsmo
;
1587 struct tevent_req
*treq
;
1589 session_info
= (struct auth_session_info
*)ldb_get_opaque(
1590 ldb_module_get_ctx(module
),
1592 level
= security_session_user_level(session_info
, NULL
);
1593 if (level
< SECURITY_ADMINISTRATOR
) {
1594 return ldb_error(ldb
, LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
, "Denied rootDSE modify for non-administrator");
1597 ret
= samdb_rodc(ldb
, &am_rodc
);
1598 if (ret
!= LDB_SUCCESS
) {
1599 return ldb_error(ldb
, ret
, "Could not determine if server is RODC.");
1603 return ldb_error(ldb
, LDB_ERR_UNWILLING_TO_PERFORM
,
1604 "RODC cannot become a role master.");
1608 * We always delete the transaction, not commit it, because
1609 * this gives the least surprise to this surprising action (as
1610 * we will never record anything done to this point
1612 rootdse_del_trans(module
);
1615 * We must use the global event loop to run this IRPC in
1616 * single process mode
1618 ldb_handle_use_global_event_context(req
->handle
);
1620 msg
= imessaging_client_init(tmp_ctx
, lp_ctx
,
1621 ldb_get_event_context(ldb
));
1623 ldb_asprintf_errstring(ldb
, "Failed to generate client messaging context in %s", lpcfg_imessaging_path(tmp_ctx
, lp_ctx
));
1624 return LDB_ERR_OPERATIONS_ERROR
;
1626 irpc_handle
= irpc_binding_handle_by_name(tmp_ctx
, msg
,
1629 if (irpc_handle
== NULL
) {
1630 return ldb_oom(ldb
);
1632 fsmo
= talloc_zero(req
, struct fsmo_transfer_state
);
1634 return ldb_oom(ldb
);
1638 fsmo
->module
= module
;
1641 * we send the call asynchronously, as the ldap client is
1642 * expecting to get an error back if the role transfer fails
1644 * We need more than the default 10 seconds IRPC allows, so
1645 * set a longer timeout (default ldb timeout is 300 seconds).
1646 * We send an async reply when we are done.
1648 * We are the first module, so don't bother working out how
1649 * long we have spent so far.
1651 dcerpc_binding_handle_set_timeout(irpc_handle
, req
->timeout
);
1653 treq
= dcerpc_drepl_takeFSMORole_send(req
, ldb_get_event_context(ldb
), irpc_handle
, role
);
1655 return ldb_oom(ldb
);
1658 tevent_req_set_callback(treq
, rootdse_fsmo_transfer_callback
, fsmo
);
1662 static int rootdse_modify(struct ldb_module
*module
, struct ldb_request
*req
)
1664 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1667 ret
= rootdse_filter_operations(module
, req
);
1668 if (ret
!= LDB_SUCCESS
) {
1672 ret
= rootdse_filter_controls(module
, req
);
1673 if (ret
!= LDB_SUCCESS
) {
1678 If dn is not "" we should let it pass through
1680 if (!ldb_dn_is_null(req
->op
.mod
.message
->dn
)) {
1681 return ldb_next_request(module
, req
);
1685 dn is empty so check for schemaUpdateNow attribute
1686 "The type of modification and values specified in the LDAP modify operation do not matter." MSDN
1688 if (ldb_msg_find_element(req
->op
.mod
.message
, "schemaUpdateNow")) {
1689 return rootdse_schemaupdatenow(module
, req
);
1691 if (ldb_msg_find_element(req
->op
.mod
.message
, "becomeDomainMaster")) {
1692 return rootdse_become_master(module
, req
, DREPL_NAMING_MASTER
);
1694 if (ldb_msg_find_element(req
->op
.mod
.message
, "becomeInfrastructureMaster")) {
1695 return rootdse_become_master(module
, req
, DREPL_INFRASTRUCTURE_MASTER
);
1697 if (ldb_msg_find_element(req
->op
.mod
.message
, "becomeRidMaster")) {
1698 return rootdse_become_master(module
, req
, DREPL_RID_MASTER
);
1700 if (ldb_msg_find_element(req
->op
.mod
.message
, "becomeSchemaMaster")) {
1701 return rootdse_become_master(module
, req
, DREPL_SCHEMA_MASTER
);
1703 if (ldb_msg_find_element(req
->op
.mod
.message
, "becomePdc")) {
1704 return rootdse_become_master(module
, req
, DREPL_PDC_MASTER
);
1706 if (ldb_msg_find_element(req
->op
.mod
.message
, "enableOptionalFeature")) {
1707 return rootdse_enableoptionalfeature(module
, req
);
1709 if (ldb_msg_find_element(req
->op
.mod
.message
, "schemaUpgradeInProgress")) {
1710 return rootdse_schemaupgradeinprogress(module
, req
);
1713 ldb_set_errstring(ldb
, "rootdse_modify: unknown attribute to change!");
1714 return LDB_ERR_UNWILLING_TO_PERFORM
;
1717 static int rootdse_rename(struct ldb_module
*module
, struct ldb_request
*req
)
1719 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1722 ret
= rootdse_filter_operations(module
, req
);
1723 if (ret
!= LDB_SUCCESS
) {
1727 ret
= rootdse_filter_controls(module
, req
);
1728 if (ret
!= LDB_SUCCESS
) {
1733 If dn is not "" we should let it pass through
1735 if (!ldb_dn_is_null(req
->op
.rename
.olddn
)) {
1736 return ldb_next_request(module
, req
);
1739 ldb_set_errstring(ldb
, "rootdse_remove: you cannot rename the rootdse entry!");
1740 return LDB_ERR_NO_SUCH_OBJECT
;
1743 static int rootdse_delete(struct ldb_module
*module
, struct ldb_request
*req
)
1745 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1748 ret
= rootdse_filter_operations(module
, req
);
1749 if (ret
!= LDB_SUCCESS
) {
1753 ret
= rootdse_filter_controls(module
, req
);
1754 if (ret
!= LDB_SUCCESS
) {
1759 If dn is not "" we should let it pass through
1761 if (!ldb_dn_is_null(req
->op
.del
.dn
)) {
1762 return ldb_next_request(module
, req
);
1765 ldb_set_errstring(ldb
, "rootdse_remove: you cannot delete the rootdse entry!");
1766 return LDB_ERR_NO_SUCH_OBJECT
;
1769 static int rootdse_extended(struct ldb_module
*module
, struct ldb_request
*req
)
1773 ret
= rootdse_filter_operations(module
, req
);
1774 if (ret
!= LDB_SUCCESS
) {
1778 ret
= rootdse_filter_controls(module
, req
);
1779 if (ret
!= LDB_SUCCESS
) {
1783 return ldb_next_request(module
, req
);
1786 static const struct ldb_module_ops ldb_rootdse_module_ops
= {
1788 .init_context
= rootdse_init
,
1789 .search
= rootdse_search
,
1790 .request
= rootdse_request
,
1792 .modify
= rootdse_modify
,
1793 .rename
= rootdse_rename
,
1794 .extended
= rootdse_extended
,
1795 .del
= rootdse_delete
,
1796 .start_transaction
= rootdse_start_trans
,
1797 .end_transaction
= rootdse_end_trans
,
1798 .del_transaction
= rootdse_del_trans
1801 int ldb_rootdse_module_init(const char *version
)
1803 LDB_MODULE_CHECK_VERSION(version
);
1804 return ldb_register_module(&ldb_rootdse_module_ops
);