dsdb: Rename private_data to rootdse_private_data in rootdse
[samba.git] / source4 / dsdb / samdb / ldb_modules / rootdse.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    rootDSE ldb module
5
6    Copyright (C) Andrew Tridgell 2005
7    Copyright (C) Simo Sorce 2005-2008
8    Copyright (C) Matthieu Patou <mat@matws.net> 2011
9
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.
14
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.
19
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/>.
22 */
23
24 #include "includes.h"
25 #include <ldb.h>
26 #include <ldb_module.h>
27 #include "system/time.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "version.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
40 struct rootdse_private_data {
41         unsigned int num_controls;
42         char **controls;
43         unsigned int num_partitions;
44         struct ldb_dn **partitions;
45         bool block_anonymous;
46 };
47
48 struct rootdse_context {
49         struct ldb_module *module;
50         struct ldb_request *req;
51         struct ldb_val netlogon;
52 };
53
54 /*
55   return 1 if a specific attribute has been requested
56 */
57 static int do_attribute(const char * const *attrs, const char *name)
58 {
59         return attrs == NULL ||
60                 ldb_attr_in_list(attrs, name) ||
61                 ldb_attr_in_list(attrs, "*");
62 }
63
64 static int do_attribute_explicit(const char * const *attrs, const char *name)
65 {
66         return attrs != NULL && ldb_attr_in_list(attrs, name);
67 }
68
69
70 /*
71   expand a DN attribute to include extended DN information if requested
72  */
73 static int expand_dn_in_message(struct ldb_module *module, struct ldb_message *msg,
74                                 const char *attrname, struct ldb_control *edn_control,
75                                 struct ldb_request *req)
76 {
77         struct ldb_dn *dn, *dn2;
78         struct ldb_val *v;
79         int ret;
80         struct ldb_request *req2;
81         char *dn_string;
82         const char *no_attrs[] = { NULL };
83         struct ldb_result *res;
84         struct ldb_extended_dn_control *edn;
85         TALLOC_CTX *tmp_ctx = talloc_new(req);
86         struct ldb_context *ldb;
87         int edn_type = 0;
88         unsigned int i;
89         struct ldb_message_element *el;
90
91         ldb = ldb_module_get_ctx(module);
92
93         edn = talloc_get_type(edn_control->data, struct ldb_extended_dn_control);
94         if (edn) {
95                 edn_type = edn->type;
96         }
97
98         el = ldb_msg_find_element(msg, attrname);
99         if (!el || el->num_values == 0) {
100                 return LDB_SUCCESS;
101         }
102
103         for (i = 0; i < el->num_values; i++) {
104                 v = &el->values[i];
105                 if (v == NULL) {
106                         talloc_free(tmp_ctx);
107                         return LDB_SUCCESS;
108                 }
109
110                 dn_string = talloc_strndup(tmp_ctx, (const char *)v->data, v->length);
111                 if (dn_string == NULL) {
112                         talloc_free(tmp_ctx);
113                         return ldb_operr(ldb);
114                 }
115
116                 res = talloc_zero(tmp_ctx, struct ldb_result);
117                 if (res == NULL) {
118                         talloc_free(tmp_ctx);
119                         return ldb_operr(ldb);
120                 }
121
122                 dn = ldb_dn_new(tmp_ctx, ldb, dn_string);
123                 if (dn == NULL) {
124                         talloc_free(tmp_ctx);
125                         return ldb_operr(ldb);
126                 }
127
128                 ret = ldb_build_search_req(&req2, ldb, tmp_ctx,
129                                         dn,
130                                         LDB_SCOPE_BASE,
131                                         NULL,
132                                         no_attrs,
133                                         NULL,
134                                         res, ldb_search_default_callback,
135                                         req);
136                 LDB_REQ_SET_LOCATION(req2);
137                 if (ret != LDB_SUCCESS) {
138                         talloc_free(tmp_ctx);
139                         return ret;
140                 }
141
142
143                 ret = ldb_request_add_control(req2,
144                                         LDB_CONTROL_EXTENDED_DN_OID,
145                                         edn_control->critical, edn);
146                 if (ret != LDB_SUCCESS) {
147                         talloc_free(tmp_ctx);
148                         return ldb_error(ldb, ret, "Failed to add control");
149                 }
150
151                 ret = ldb_next_request(module, req2);
152                 if (ret == LDB_SUCCESS) {
153                         ret = ldb_wait(req2->handle, LDB_WAIT_ALL);
154                 }
155
156                 if (ret != LDB_SUCCESS) {
157                         talloc_free(tmp_ctx);
158                         return ret;
159                 }
160
161                 if (!res || res->count != 1) {
162                         talloc_free(tmp_ctx);
163                         return ldb_operr(ldb);
164                 }
165
166                 dn2 = res->msgs[0]->dn;
167
168                 v->data = (uint8_t *)ldb_dn_get_extended_linearized(msg->elements, dn2, edn_type);
169                 if (v->data == NULL) {
170                         talloc_free(tmp_ctx);
171                         return ldb_operr(ldb);
172                 }
173                 v->length = strlen((char *)v->data);
174         }
175
176         talloc_free(tmp_ctx);
177
178         return LDB_SUCCESS;
179 }
180
181 /*
182   see if we are master for a FSMO role
183  */
184 static int dsdb_module_we_are_master(struct ldb_module *module, struct ldb_dn *dn, bool *master,
185                                      struct ldb_request *parent)
186 {
187         const char *attrs[] = { "fSMORoleOwner", NULL };
188         TALLOC_CTX *tmp_ctx = talloc_new(parent);
189         struct ldb_result *res;
190         int ret;
191         struct ldb_dn *owner_dn;
192
193         ret = dsdb_module_search_dn(module, tmp_ctx, &res,
194                                     dn, attrs,
195                                     DSDB_FLAG_NEXT_MODULE |
196                                     DSDB_FLAG_AS_SYSTEM |
197                                     DSDB_SEARCH_SHOW_EXTENDED_DN,
198                                     parent);
199         if (ret != LDB_SUCCESS) {
200                 talloc_free(tmp_ctx);
201                 return ret;
202         }
203
204         owner_dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
205                                            tmp_ctx, res->msgs[0], "fSMORoleOwner");
206         if (!owner_dn) {
207                 *master = false;
208                 talloc_free(tmp_ctx);
209                 return LDB_SUCCESS;
210         }
211
212         ret = samdb_dn_is_our_ntdsa(ldb_module_get_ctx(module), dn, master);
213         if (ret != LDB_SUCCESS) {
214                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to confirm if our ntdsDsa is %s: %s",
215                                        ldb_dn_get_linearized(owner_dn), ldb_errstring(ldb_module_get_ctx(module)));
216                 talloc_free(tmp_ctx);
217                 return ret;
218         }
219         
220         talloc_free(tmp_ctx);
221         return LDB_SUCCESS;
222 }
223
224 /*
225   add dynamically generated attributes to rootDSE result
226 */
227 static int rootdse_add_dynamic(struct rootdse_context *ac, struct ldb_message *msg)
228 {
229         struct ldb_context *ldb;
230         struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(ac->module), struct rootdse_private_data);
231         const char * const *attrs = ac->req->op.search.attrs;
232         char **server_sasl;
233         const struct dsdb_schema *schema;
234         int *val;
235         struct ldb_control *edn_control;
236         const char *dn_attrs[] = {
237                 "configurationNamingContext",
238                 "defaultNamingContext",
239                 "rootDomainNamingContext",
240                 "schemaNamingContext",
241                 "serverName",
242                 "validFSMOs",
243                 "namingContexts",
244                 NULL
245         };
246         const char *guid_attrs[] = {
247                 "dsServiceName",
248                 NULL
249         };
250         unsigned int i;
251
252         ldb = ldb_module_get_ctx(ac->module);
253         schema = dsdb_get_schema(ldb, NULL);
254
255         msg->dn = ldb_dn_new(msg, ldb, NULL);
256
257         /* don't return the distinguishedName, cn and name attributes */
258         ldb_msg_remove_attr(msg, "distinguishedName");
259         ldb_msg_remove_attr(msg, "cn");
260         ldb_msg_remove_attr(msg, "name");
261
262         if (do_attribute(attrs, "serverName")) {
263                 if (ldb_msg_add_linearized_dn(msg, "serverName",
264                         samdb_server_dn(ldb, msg)) != LDB_SUCCESS) {
265                         goto failed;
266                 }
267         }
268
269         if (do_attribute(attrs, "dnsHostName")) {
270                 struct ldb_result *res;
271                 int ret;
272                 const char *dns_attrs[] = { "dNSHostName", NULL };
273                 ret = dsdb_module_search_dn(ac->module, msg, &res, samdb_server_dn(ldb, msg),
274                                             dns_attrs,
275                                             DSDB_FLAG_NEXT_MODULE |
276                                             DSDB_FLAG_AS_SYSTEM,
277                                             ac->req);
278                 if (ret == LDB_SUCCESS) {
279                         const char *hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
280                         if (hostname != NULL) {
281                                 if (ldb_msg_add_string(msg, "dnsHostName", hostname)) {
282                                         goto failed;
283                                 }
284                         }
285                 }
286         }
287
288         if (do_attribute(attrs, "ldapServiceName")) {
289                 struct loadparm_context *lp_ctx
290                         = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
291                                           struct loadparm_context);
292                 char *ldap_service_name, *hostname;
293
294                 hostname = strlower_talloc(msg, lpcfg_netbios_name(lp_ctx));
295                 if (hostname == NULL) {
296                         goto failed;
297                 }
298
299                 ldap_service_name = talloc_asprintf(msg, "%s:%s$@%s",
300                                                     samdb_forest_name(ldb, msg),
301                                                     hostname, lpcfg_realm(lp_ctx));
302                 if (ldap_service_name == NULL) {
303                         goto failed;
304                 }
305
306                 if (ldb_msg_add_string(msg, "ldapServiceName",
307                                        ldap_service_name) != LDB_SUCCESS) {
308                         goto failed;
309                 }
310         }
311
312         if (do_attribute(attrs, "currentTime")) {
313                 if (ldb_msg_add_steal_string(msg, "currentTime",
314                                              ldb_timestring(msg, time(NULL))) != LDB_SUCCESS) {
315                         goto failed;
316                 }
317         }
318
319         if (priv && do_attribute(attrs, "supportedControl")) {
320                 for (i = 0; i < priv->num_controls; i++) {
321                         char *control = talloc_strdup(msg, priv->controls[i]);
322                         if (!control) {
323                                 goto failed;
324                         }
325                         if (ldb_msg_add_steal_string(msg, "supportedControl",
326                                                      control) != LDB_SUCCESS) {
327                                 goto failed;
328                         }
329                 }
330         }
331
332         if (priv && do_attribute(attrs, "namingContexts")) {
333                 for (i = 0; i < priv->num_partitions; i++) {
334                         struct ldb_dn *dn = priv->partitions[i];
335                         if (ldb_msg_add_steal_string(msg, "namingContexts",
336                                                      ldb_dn_alloc_linearized(msg, dn)) != LDB_SUCCESS) {
337                                 goto failed;
338                         }
339                 }
340         }
341
342         server_sasl = talloc_get_type(ldb_get_opaque(ldb, "supportedSASLMechanisms"),
343                                        char *);
344         if (server_sasl && do_attribute(attrs, "supportedSASLMechanisms")) {
345                 for (i = 0; server_sasl && server_sasl[i]; i++) {
346                         char *sasl_name = talloc_strdup(msg, server_sasl[i]);
347                         if (!sasl_name) {
348                                 goto failed;
349                         }
350                         if (ldb_msg_add_steal_string(msg, "supportedSASLMechanisms",
351                                                      sasl_name) != LDB_SUCCESS) {
352                                 goto failed;
353                         }
354                 }
355         }
356
357         if (do_attribute(attrs, "highestCommittedUSN")) {
358                 uint64_t seq_num;
359                 int ret = ldb_sequence_number(ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
360                 if (ret == LDB_SUCCESS) {
361                         if (samdb_msg_add_uint64(ldb, msg, msg,
362                                                  "highestCommittedUSN",
363                                                  seq_num) != LDB_SUCCESS) {
364                                 goto failed;
365                         }
366                 }
367         }
368
369         if (schema && do_attribute_explicit(attrs, "dsSchemaAttrCount")) {
370                 struct dsdb_attribute *cur;
371                 unsigned int n = 0;
372
373                 for (cur = schema->attributes; cur; cur = cur->next) {
374                         n++;
375                 }
376
377                 if (samdb_msg_add_uint(ldb, msg, msg, "dsSchemaAttrCount",
378                                        n) != LDB_SUCCESS) {
379                         goto failed;
380                 }
381         }
382
383         if (schema && do_attribute_explicit(attrs, "dsSchemaClassCount")) {
384                 struct dsdb_class *cur;
385                 unsigned int n = 0;
386
387                 for (cur = schema->classes; cur; cur = cur->next) {
388                         n++;
389                 }
390
391                 if (samdb_msg_add_uint(ldb, msg, msg, "dsSchemaClassCount",
392                                        n) != LDB_SUCCESS) {
393                         goto failed;
394                 }
395         }
396
397         if (schema && do_attribute_explicit(attrs, "dsSchemaPrefixCount")) {
398                 if (samdb_msg_add_uint(ldb, msg, msg, "dsSchemaPrefixCount",
399                                        schema->prefixmap->length) != LDB_SUCCESS) {
400                         goto failed;
401                 }
402         }
403
404         if (do_attribute_explicit(attrs, "validFSMOs")) {
405                 struct ldb_dn *dns[3];
406
407                 dns[0] = ldb_get_schema_basedn(ldb);
408                 dns[1] = samdb_partitions_dn(ldb, msg);
409                 dns[2] = ldb_get_default_basedn(ldb);
410
411                 for (i=0; i<3; i++) {
412                         bool master;
413                         int ret = dsdb_module_we_are_master(ac->module, dns[i], &master, ac->req);
414                         if (ret != LDB_SUCCESS) {
415                                 goto failed;
416                         }
417                         if (master && ldb_msg_add_fmt(msg, "validFSMOs", "%s",
418                                                       ldb_dn_get_linearized(dns[i])) != LDB_SUCCESS) {
419                                 goto failed;
420                         }
421                 }
422         }
423
424         if (do_attribute_explicit(attrs, "vendorVersion")) {
425                 if (ldb_msg_add_fmt(msg, "vendorVersion",
426                                     "%s", SAMBA_VERSION_STRING) != LDB_SUCCESS) {
427                         goto failed;
428                 }
429         }
430
431         if (do_attribute(attrs, "domainFunctionality")) {
432                 if (samdb_msg_add_int(ldb, msg, msg, "domainFunctionality",
433                                       dsdb_functional_level(ldb)) != LDB_SUCCESS) {
434                         goto failed;
435                 }
436         }
437
438         if (do_attribute(attrs, "forestFunctionality")) {
439                 if (samdb_msg_add_int(ldb, msg, msg, "forestFunctionality",
440                                       dsdb_forest_functional_level(ldb)) != LDB_SUCCESS) {
441                         goto failed;
442                 }
443         }
444
445         if (do_attribute(attrs, "domainControllerFunctionality")
446             && (val = talloc_get_type(ldb_get_opaque(ldb, "domainControllerFunctionality"), int))) {
447                 if (samdb_msg_add_int(ldb, msg, msg,
448                                       "domainControllerFunctionality",
449                                       *val) != LDB_SUCCESS) {
450                         goto failed;
451                 }
452         }
453
454         if (do_attribute(attrs, "isGlobalCatalogReady")) {
455                 /* MS-ADTS 3.1.1.3.2.10
456                    Note, we should only return true here is we have
457                    completed at least one synchronisation. As both
458                    provision and vampire do a full sync, this means we
459                    can return true is the gc bit is set in the NTDSDSA
460                    options */
461                 if (ldb_msg_add_fmt(msg, "isGlobalCatalogReady",
462                                     "%s", samdb_is_gc(ldb)?"TRUE":"FALSE") != LDB_SUCCESS) {
463                         goto failed;
464                 }
465         }
466
467         if (do_attribute_explicit(attrs, "tokenGroups")) {
468                 /* Obtain the user's session_info */
469                 struct auth_session_info *session_info
470                         = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
471                 if (session_info && session_info->security_token) {
472                         /* The list of groups this user is in */
473                         for (i = 0; i < session_info->security_token->num_sids; i++) {
474                                 if (samdb_msg_add_dom_sid(ldb, msg, msg,
475                                                           "tokenGroups",
476                                                           &session_info->security_token->sids[i]) != LDB_SUCCESS) {
477                                         goto failed;
478                                 }
479                         }
480                 }
481         }
482
483         if (ac->netlogon.length > 0) {
484                 if (ldb_msg_add_steal_value(msg, "netlogon", &ac->netlogon) != LDB_SUCCESS) {
485                         goto failed;
486                 }
487         }
488
489         /* TODO: lots more dynamic attributes should be added here */
490
491         edn_control = ldb_request_get_control(ac->req, LDB_CONTROL_EXTENDED_DN_OID);
492
493         /* convert any GUID attributes to be in the right form */
494         for (i=0; guid_attrs[i]; i++) {
495                 struct ldb_result *res;
496                 struct ldb_message_element *el;
497                 struct ldb_dn *attr_dn;
498                 const char *no_attrs[] = { NULL };
499                 int ret;
500
501                 if (!do_attribute(attrs, guid_attrs[i])) continue;
502
503                 attr_dn = ldb_msg_find_attr_as_dn(ldb, ac->req, msg, guid_attrs[i]);
504                 if (attr_dn == NULL) {
505                         continue;
506                 }
507
508                 ret = dsdb_module_search_dn(ac->module, ac->req, &res,
509                                             attr_dn, no_attrs,
510                                             DSDB_FLAG_NEXT_MODULE |
511                                             DSDB_FLAG_AS_SYSTEM |
512                                             DSDB_SEARCH_SHOW_EXTENDED_DN,
513                                             ac->req);
514                 if (ret != LDB_SUCCESS) {
515                         return ldb_operr(ldb);
516                 }
517
518                 el = ldb_msg_find_element(msg, guid_attrs[i]);
519                 if (el == NULL) {
520                         return ldb_operr(ldb);
521                 }
522
523                 talloc_steal(el->values, res->msgs[0]->dn);
524                 if (edn_control) {
525                         struct ldb_extended_dn_control *edn;
526                         int edn_type = 0;
527                         edn = talloc_get_type(edn_control->data, struct ldb_extended_dn_control);
528                         if (edn != NULL) {
529                                 edn_type = edn->type;
530                         }
531                         el->values[0].data  = (uint8_t *)ldb_dn_get_extended_linearized(el->values,
532                                                                                         res->msgs[0]->dn,
533                                                                                         edn_type);
534                 } else {
535                         el->values[0].data  = (uint8_t *)talloc_strdup(el->values,
536                                                                        ldb_dn_get_linearized(res->msgs[0]->dn));
537                 }
538                 if (el->values[0].data == NULL) {
539                         return ldb_oom(ldb);
540                 }
541                 el->values[0].length = strlen((const char *)el->values[0].data);
542         }
543
544         /* if the client sent us the EXTENDED_DN control then we need
545            to expand the DNs to have GUID and SID. W2K8 join relies on
546            this */
547         if (edn_control) {
548                 int ret;
549                 for (i=0; dn_attrs[i]; i++) {
550                         if (!do_attribute(attrs, dn_attrs[i])) continue;
551                         ret = expand_dn_in_message(ac->module, msg, dn_attrs[i],
552                                                    edn_control, ac->req);
553                         if (ret != LDB_SUCCESS) {
554                                 DEBUG(0,(__location__ ": Failed to expand DN in rootDSE for %s\n",
555                                          dn_attrs[i]));
556                                 goto failed;
557                         }
558                 }
559         }
560
561         return LDB_SUCCESS;
562
563 failed:
564         return ldb_operr(ldb);
565 }
566
567 /*
568   handle search requests
569 */
570
571 static struct rootdse_context *rootdse_init_context(struct ldb_module *module,
572                                                     struct ldb_request *req)
573 {
574         struct ldb_context *ldb;
575         struct rootdse_context *ac;
576
577         ldb = ldb_module_get_ctx(module);
578
579         ac = talloc_zero(req, struct rootdse_context);
580         if (ac == NULL) {
581                 ldb_set_errstring(ldb, "Out of Memory");
582                 return NULL;
583         }
584
585         ac->module = module;
586         ac->req = req;
587
588         return ac;
589 }
590
591 static int rootdse_callback(struct ldb_request *req, struct ldb_reply *ares)
592 {
593         struct rootdse_context *ac;
594         int ret;
595
596         ac = talloc_get_type(req->context, struct rootdse_context);
597
598         if (!ares) {
599                 return ldb_module_done(ac->req, NULL, NULL,
600                                         LDB_ERR_OPERATIONS_ERROR);
601         }
602         if (ares->error != LDB_SUCCESS) {
603                 return ldb_module_done(ac->req, ares->controls,
604                                         ares->response, ares->error);
605         }
606
607         switch (ares->type) {
608         case LDB_REPLY_ENTRY:
609                 /* for each record returned post-process to add any dynamic
610                    attributes that have been asked for */
611                 ret = rootdse_add_dynamic(ac, ares->message);
612                 if (ret != LDB_SUCCESS) {
613                         talloc_free(ares);
614                         return ldb_module_done(ac->req, NULL, NULL, ret);
615                 }
616
617                 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
618
619         case LDB_REPLY_REFERRAL:
620                 /* should we allow the backend to return referrals in this case
621                  * ?? */
622                 break;
623
624         case LDB_REPLY_DONE:
625                 return ldb_module_done(ac->req, ares->controls,
626                                         ares->response, ares->error);
627         }
628
629         talloc_free(ares);
630         return LDB_SUCCESS;
631 }
632
633 /*
634   filter from controls from clients in several ways
635
636   1) mark our registered controls as non-critical in the request
637
638     This is needed as clients may mark controls as critical even if
639     they are not needed at all in a request. For example, the centrify
640     client sets the SD_FLAGS control as critical on ldap modify
641     requests which are setting the dNSHostName attribute on the
642     machine account. That request doesn't need SD_FLAGS at all, but
643     centrify adds it on all ldap requests.
644
645   2) if this request is untrusted then remove any non-registered
646      controls that are non-critical
647
648     This is used on ldap:// connections to prevent remote users from
649     setting an internal control that may be dangerous
650
651   3) if this request is untrusted then fail any request that includes
652      a critical non-registered control
653  */
654 static int rootdse_filter_controls(struct ldb_module *module, struct ldb_request *req)
655 {
656         unsigned int i, j;
657         struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data);
658         bool is_untrusted;
659
660         if (!req->controls) {
661                 return LDB_SUCCESS;
662         }
663
664         is_untrusted = ldb_req_is_untrusted(req);
665
666         for (i=0; req->controls[i]; i++) {
667                 bool is_registered = false;
668                 bool is_critical = (req->controls[i]->critical != 0);
669
670                 if (req->controls[i]->oid == NULL) {
671                         continue;
672                 }
673
674                 if (is_untrusted || is_critical) {
675                         for (j=0; j<priv->num_controls; j++) {
676                                 if (strcasecmp(priv->controls[j], req->controls[i]->oid) == 0) {
677                                         is_registered = true;
678                                         break;
679                                 }
680                         }
681                 }
682
683                 if (is_untrusted && !is_registered) {
684                         if (!is_critical) {
685                                 /* remove it by marking the oid NULL */
686                                 req->controls[i]->oid = NULL;
687                                 req->controls[i]->data = NULL;
688                                 req->controls[i]->critical = 0;
689                                 continue;
690                         }
691                         /* its a critical unregistered control - give
692                            an error */
693                         ldb_asprintf_errstring(ldb_module_get_ctx(module),
694                                                "Attempt to use critical non-registered control '%s'",
695                                                req->controls[i]->oid);
696                         return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
697                 }
698
699                 if (!is_critical) {
700                         continue;
701                 }
702
703                 /* If the control is DIRSYNC control then we keep the critical
704                  * flag as the dirsync module will need to act upon it
705                  */
706                 if (is_registered && strcmp(req->controls[i]->oid,
707                                         LDB_CONTROL_DIRSYNC_OID)!= 0) {
708                         req->controls[i]->critical = 0;
709                 }
710         }
711
712         return LDB_SUCCESS;
713 }
714
715 /* Ensure that anonymous users are not allowed to make anything other than rootDSE search operations */
716
717 static int rootdse_filter_operations(struct ldb_module *module, struct ldb_request *req)
718 {
719         struct auth_session_info *session_info;
720         struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data);
721         bool is_untrusted = ldb_req_is_untrusted(req);
722         bool is_anonymous = true;
723         if (is_untrusted == false) {
724                 return LDB_SUCCESS;
725         }
726
727         session_info = (struct auth_session_info *)ldb_get_opaque(ldb_module_get_ctx(module), "sessionInfo");
728         if (session_info) {
729                 is_anonymous = security_token_is_anonymous(session_info->security_token);
730         }
731         
732         if (is_anonymous == false || (priv && priv->block_anonymous == false)) {
733                 return LDB_SUCCESS;
734         }
735         
736         if (req->operation == LDB_SEARCH) {
737                 if (req->op.search.scope == LDB_SCOPE_BASE && ldb_dn_is_null(req->op.search.base)) {
738                         return LDB_SUCCESS;
739                 }
740         }
741         ldb_set_errstring(ldb_module_get_ctx(module), "Operation unavailable without authentication");
742         return LDB_ERR_OPERATIONS_ERROR;
743 }
744
745 static int rootdse_handle_netlogon(struct rootdse_context *ac)
746 {
747         struct ldb_context *ldb;
748         struct ldb_parse_tree *tree;
749         struct loadparm_context *lp_ctx;
750         struct tsocket_address *src_addr;
751         TALLOC_CTX *tmp_ctx = talloc_new(ac->req);
752         const char *domain, *host, *user, *domain_guid;
753         char *src_addr_s = NULL;
754         struct dom_sid *domain_sid;
755         int acct_control = -1;
756         int version = -1;
757         NTSTATUS status;
758         struct netlogon_samlogon_response netlogon;
759         int ret = LDB_ERR_OPERATIONS_ERROR;
760
761         ldb = ldb_module_get_ctx(ac->module);
762         tree = ac->req->op.search.tree;
763         lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
764                                  struct loadparm_context);
765         src_addr = talloc_get_type(ldb_get_opaque(ldb, "remoteAddress"),
766                                    struct tsocket_address);
767         if (src_addr) {
768                 src_addr_s = tsocket_address_inet_addr_string(src_addr,
769                                                               tmp_ctx);
770         }
771
772         status = parse_netlogon_request(tree, lp_ctx, tmp_ctx,
773                                         &domain, &host, &user, &domain_guid,
774                                         &domain_sid, &acct_control, &version);
775         if (!NT_STATUS_IS_OK(status)) {
776                 goto failed;
777         }
778
779         status = fill_netlogon_samlogon_response(ldb, tmp_ctx,
780                                                  domain, NULL, domain_sid,
781                                                  domain_guid,
782                                                  user, acct_control,
783                                                  src_addr_s,
784                                                  version, lp_ctx,
785                                                  &netlogon, false);
786         if (!NT_STATUS_IS_OK(status)) {
787                 goto failed;
788         }
789
790         status = push_netlogon_samlogon_response(&ac->netlogon, ac, &netlogon);
791         if (!NT_STATUS_IS_OK(status)) {
792                 goto failed;
793         }
794
795         ret = LDB_SUCCESS;
796 failed:
797         talloc_free(tmp_ctx);
798         return ret;
799 }
800
801 static int rootdse_search(struct ldb_module *module, struct ldb_request *req)
802 {
803         struct ldb_context *ldb;
804         struct rootdse_context *ac;
805         struct ldb_request *down_req;
806         int ret;
807
808         ret = rootdse_filter_operations(module, req);
809         if (ret != LDB_SUCCESS) {
810                 return ret;
811         }
812
813         ret = rootdse_filter_controls(module, req);
814         if (ret != LDB_SUCCESS) {
815                 return ret;
816         }
817
818         ldb = ldb_module_get_ctx(module);
819
820         /* see if its for the rootDSE - only a base search on the "" DN qualifies */
821         if (!(req->op.search.scope == LDB_SCOPE_BASE && ldb_dn_is_null(req->op.search.base))) {
822                 /* Otherwise, pass down to the rest of the stack */
823                 return ldb_next_request(module, req);
824         }
825
826         ac = rootdse_init_context(module, req);
827         if (ac == NULL) {
828                 return ldb_operr(ldb);
829         }
830
831         if (do_attribute_explicit(req->op.search.attrs, "netlogon")) {
832                 ret = rootdse_handle_netlogon(ac);
833                 /* We have to return an empty result, so dont forward `ret' */
834                 if (ret != LDB_SUCCESS) {
835                         return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
836                 }
837         }
838
839         /* in our db we store the rootDSE with a DN of @ROOTDSE */
840         ret = ldb_build_search_req(&down_req, ldb, ac,
841                                         ldb_dn_new(ac, ldb, "@ROOTDSE"),
842                                         LDB_SCOPE_BASE,
843                                         NULL,
844                                         req->op.search.attrs,
845                                         NULL,/* for now skip the controls from the client */
846                                         ac, rootdse_callback,
847                                         req);
848         LDB_REQ_SET_LOCATION(down_req);
849         if (ret != LDB_SUCCESS) {
850                 return ret;
851         }
852
853         return ldb_next_request(module, down_req);
854 }
855
856 static int rootdse_register_control(struct ldb_module *module, struct ldb_request *req)
857 {
858         struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data);
859         char **list;
860
861         list = talloc_realloc(priv, priv->controls, char *, priv->num_controls + 1);
862         if (!list) {
863                 return ldb_oom(ldb_module_get_ctx(module));
864         }
865
866         list[priv->num_controls] = talloc_strdup(list, req->op.reg_control.oid);
867         if (!list[priv->num_controls]) {
868                 return ldb_oom(ldb_module_get_ctx(module));
869         }
870
871         priv->num_controls += 1;
872         priv->controls = list;
873
874         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
875 }
876
877 static int rootdse_register_partition(struct ldb_module *module, struct ldb_request *req)
878 {
879         struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data);
880         struct ldb_dn **list;
881
882         list = talloc_realloc(priv, priv->partitions, struct ldb_dn *, priv->num_partitions + 1);
883         if (!list) {
884                 return ldb_oom(ldb_module_get_ctx(module));
885         }
886
887         list[priv->num_partitions] = ldb_dn_copy(list, req->op.reg_partition.dn);
888         if (!list[priv->num_partitions]) {
889                 return ldb_operr(ldb_module_get_ctx(module));
890         }
891
892         priv->num_partitions += 1;
893         priv->partitions = list;
894
895         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
896 }
897
898
899 static int rootdse_request(struct ldb_module *module, struct ldb_request *req)
900 {
901         switch (req->operation) {
902
903         case LDB_REQ_REGISTER_CONTROL:
904                 return rootdse_register_control(module, req);
905         case LDB_REQ_REGISTER_PARTITION:
906                 return rootdse_register_partition(module, req);
907
908         default:
909                 break;
910         }
911         return ldb_next_request(module, req);
912 }
913
914 static int rootdse_init(struct ldb_module *module)
915 {
916         int ret;
917         struct ldb_context *ldb;
918         struct ldb_result *res;
919         struct rootdse_private_data *data;
920         const char *attrs[] = { "msDS-Behavior-Version", NULL };
921         const char *ds_attrs[] = { "dsServiceName", NULL };
922         TALLOC_CTX *mem_ctx;
923
924         ldb = ldb_module_get_ctx(module);
925
926         data = talloc_zero(module, struct rootdse_private_data);
927         if (data == NULL) {
928                 return ldb_oom(ldb);
929         }
930
931         data->num_controls = 0;
932         data->controls = NULL;
933         data->num_partitions = 0;
934         data->partitions = NULL;
935         data->block_anonymous = true;
936
937         ldb_module_set_private(module, data);
938
939         ldb_set_default_dns(ldb);
940
941         ret = ldb_next_init(module);
942
943         if (ret != LDB_SUCCESS) {
944                 return ret;
945         }
946
947         mem_ctx = talloc_new(data);
948         if (!mem_ctx) {
949                 return ldb_oom(ldb);
950         }
951
952         /* Now that the partitions are set up, do a search for:
953            - domainControllerFunctionality
954            - domainFunctionality
955            - forestFunctionality
956
957            Then stuff these values into an opaque
958         */
959         ret = dsdb_module_search(module, mem_ctx, &res,
960                                  ldb_get_default_basedn(ldb),
961                                  LDB_SCOPE_BASE, attrs,
962                                  DSDB_FLAG_NEXT_MODULE |
963                                  DSDB_FLAG_AS_SYSTEM,
964                                  NULL, NULL);
965         if (ret == LDB_SUCCESS && res->count == 1) {
966                 int domain_behaviour_version
967                         = ldb_msg_find_attr_as_int(res->msgs[0],
968                                                    "msDS-Behavior-Version", -1);
969                 if (domain_behaviour_version != -1) {
970                         int *val = talloc(ldb, int);
971                         if (!val) {
972                                 talloc_free(mem_ctx);
973                                 return ldb_oom(ldb);
974                         }
975                         *val = domain_behaviour_version;
976                         ret = ldb_set_opaque(ldb, "domainFunctionality", val);
977                         if (ret != LDB_SUCCESS) {
978                                 talloc_free(mem_ctx);
979                                 return ret;
980                         }
981                 }
982         }
983
984         ret = dsdb_module_search(module, mem_ctx, &res,
985                                  samdb_partitions_dn(ldb, mem_ctx),
986                                  LDB_SCOPE_BASE, attrs,
987                                  DSDB_FLAG_NEXT_MODULE |
988                                  DSDB_FLAG_AS_SYSTEM,
989                                  NULL, NULL);
990         if (ret == LDB_SUCCESS && res->count == 1) {
991                 int forest_behaviour_version
992                         = ldb_msg_find_attr_as_int(res->msgs[0],
993                                                    "msDS-Behavior-Version", -1);
994                 if (forest_behaviour_version != -1) {
995                         int *val = talloc(ldb, int);
996                         if (!val) {
997                                 talloc_free(mem_ctx);
998                                 return ldb_oom(ldb);
999                         }
1000                         *val = forest_behaviour_version;
1001                         ret = ldb_set_opaque(ldb, "forestFunctionality", val);
1002                         if (ret != LDB_SUCCESS) {
1003                                 talloc_free(mem_ctx);
1004                                 return ret;
1005                         }
1006                 }
1007         }
1008
1009         /* For now, our own server's location in the DB is recorded in
1010          * the @ROOTDSE record */
1011         ret = dsdb_module_search(module, mem_ctx, &res,
1012                                  ldb_dn_new(mem_ctx, ldb, "@ROOTDSE"),
1013                                  LDB_SCOPE_BASE, ds_attrs,
1014                                  DSDB_FLAG_NEXT_MODULE |
1015                                  DSDB_FLAG_AS_SYSTEM,
1016                                  NULL, NULL);
1017         if (ret == LDB_SUCCESS && res->count == 1) {
1018                 struct ldb_dn *ds_dn
1019                         = ldb_msg_find_attr_as_dn(ldb, mem_ctx, res->msgs[0],
1020                                                   "dsServiceName");
1021                 if (ds_dn) {
1022                         ret = dsdb_module_search(module, mem_ctx, &res, ds_dn,
1023                                                  LDB_SCOPE_BASE, attrs,
1024                                                  DSDB_FLAG_NEXT_MODULE |
1025                                                  DSDB_FLAG_AS_SYSTEM,
1026                                                  NULL, NULL);
1027                         if (ret == LDB_SUCCESS && res->count == 1) {
1028                                 int domain_controller_behaviour_version
1029                                         = ldb_msg_find_attr_as_int(res->msgs[0],
1030                                                                    "msDS-Behavior-Version", -1);
1031                                 if (domain_controller_behaviour_version != -1) {
1032                                         int *val = talloc(ldb, int);
1033                                         if (!val) {
1034                                                 talloc_free(mem_ctx);
1035                                                 return ldb_oom(ldb);
1036                                         }
1037                                         *val = domain_controller_behaviour_version;
1038                                         ret = ldb_set_opaque(ldb,
1039                                                              "domainControllerFunctionality", val);
1040                                         if (ret != LDB_SUCCESS) {
1041                                                 talloc_free(mem_ctx);
1042                                                 return ret;
1043                                         }
1044                                 }
1045                         }
1046                 }
1047         }
1048
1049         data->block_anonymous = dsdb_block_anonymous_ops(module, NULL);
1050
1051         talloc_free(mem_ctx);
1052
1053         return LDB_SUCCESS;
1054 }
1055
1056 /*
1057  * This function gets the string SCOPE_DN:OPTIONAL_FEATURE_GUID and parse it
1058  * to a DN and a GUID object
1059  */
1060 static int get_optional_feature_dn_guid(struct ldb_request *req, struct ldb_context *ldb,
1061                                                 TALLOC_CTX *mem_ctx,
1062                                                 struct ldb_dn **op_feature_scope_dn,
1063                                                 struct GUID *op_feature_guid)
1064 {
1065         const struct ldb_message *msg = req->op.mod.message;
1066         const char *ldb_val_str;
1067         char *dn, *guid;
1068         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1069         NTSTATUS status;
1070
1071         ldb_val_str = ldb_msg_find_attr_as_string(msg, "enableOptionalFeature", NULL);
1072         if (!ldb_val_str) {
1073                 ldb_set_errstring(ldb,
1074                                   "rootdse: unable to find 'enableOptionalFeature'!");
1075                 return LDB_ERR_UNWILLING_TO_PERFORM;
1076         }
1077
1078         guid = strchr(ldb_val_str, ':');
1079         if (!guid) {
1080                 ldb_set_errstring(ldb,
1081                                   "rootdse: unable to find GUID in 'enableOptionalFeature'!");
1082                 return LDB_ERR_UNWILLING_TO_PERFORM;
1083         }
1084         status = GUID_from_string(guid+1, op_feature_guid);
1085         if (!NT_STATUS_IS_OK(status)) {
1086                 ldb_set_errstring(ldb,
1087                                   "rootdse: bad GUID in 'enableOptionalFeature'!");
1088                 return LDB_ERR_UNWILLING_TO_PERFORM;
1089         }
1090
1091         dn = talloc_strndup(tmp_ctx, ldb_val_str, guid-ldb_val_str);
1092         if (!dn) {
1093                 ldb_set_errstring(ldb,
1094                                   "rootdse: bad DN in 'enableOptionalFeature'!");
1095                 return LDB_ERR_UNWILLING_TO_PERFORM;
1096         }
1097
1098         *op_feature_scope_dn = ldb_dn_new(mem_ctx, ldb, dn);
1099
1100         talloc_free(tmp_ctx);
1101         return LDB_SUCCESS;
1102 }
1103
1104 /*
1105  * This function gets the OPTIONAL_FEATURE_GUID and looks for the optional feature
1106  * ldb_message object.
1107  */
1108 static int dsdb_find_optional_feature(struct ldb_module *module, struct ldb_context *ldb,
1109                                       TALLOC_CTX *mem_ctx, struct GUID op_feature_guid, struct ldb_message **msg,
1110                                       struct ldb_request *parent)
1111 {
1112         struct ldb_result *res;
1113         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1114         int ret;
1115
1116         ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
1117                                  NULL,
1118                                  DSDB_FLAG_NEXT_MODULE |
1119                                  DSDB_FLAG_AS_SYSTEM |
1120                                  DSDB_SEARCH_SEARCH_ALL_PARTITIONS,
1121                                  parent,
1122                                  "(&(objectClass=msDS-OptionalFeature)"
1123                                  "(msDS-OptionalFeatureGUID=%s))",GUID_string(tmp_ctx, &op_feature_guid));
1124
1125         if (ret != LDB_SUCCESS) {
1126                 talloc_free(tmp_ctx);
1127                 return ret;
1128         }
1129         if (res->count == 0) {
1130                 talloc_free(tmp_ctx);
1131                 return LDB_ERR_NO_SUCH_OBJECT;
1132         }
1133         if (res->count != 1) {
1134                 ldb_asprintf_errstring(ldb,
1135                                        "More than one object found matching optional feature GUID %s\n",
1136                                        GUID_string(tmp_ctx, &op_feature_guid));
1137                 talloc_free(tmp_ctx);
1138                 return LDB_ERR_OPERATIONS_ERROR;
1139         }
1140
1141         *msg = talloc_steal(mem_ctx, res->msgs[0]);
1142
1143         talloc_free(tmp_ctx);
1144         return LDB_SUCCESS;
1145 }
1146
1147 static int rootdse_enable_recycle_bin(struct ldb_module *module,struct ldb_context *ldb,
1148                                       TALLOC_CTX *mem_ctx, struct ldb_dn *op_feature_scope_dn,
1149                                       struct ldb_message *op_feature_msg, struct ldb_request *parent)
1150 {
1151         int ret;
1152         const int domain_func_level = dsdb_functional_level(ldb);
1153         struct ldb_dn *ntds_settings_dn;
1154         TALLOC_CTX *tmp_ctx;
1155         unsigned int el_count = 0;
1156         struct ldb_message *msg;
1157
1158         ret = ldb_msg_find_attr_as_int(op_feature_msg, "msDS-RequiredForestBehaviorVersion", 0);
1159         if (domain_func_level < ret){
1160                 ldb_asprintf_errstring(ldb,
1161                                        "rootdse_enable_recycle_bin: Domain functional level must be at least %d\n",
1162                                        ret);
1163                 return LDB_ERR_UNWILLING_TO_PERFORM;
1164         }
1165
1166         tmp_ctx = talloc_new(mem_ctx);
1167         ntds_settings_dn = samdb_ntds_settings_dn(ldb, tmp_ctx);
1168         if (!ntds_settings_dn) {
1169                 talloc_free(tmp_ctx);
1170                 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "Failed to find NTDS settings DN");
1171         }
1172
1173         ntds_settings_dn = ldb_dn_copy(tmp_ctx, ntds_settings_dn);
1174         if (!ntds_settings_dn) {
1175                 talloc_free(tmp_ctx);
1176                 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "Failed to copy NTDS settings DN");
1177         }
1178
1179         msg = ldb_msg_new(tmp_ctx);
1180         msg->dn = ntds_settings_dn;
1181
1182         ldb_msg_add_linearized_dn(msg, "msDS-EnabledFeature", op_feature_msg->dn);
1183         msg->elements[el_count++].flags = LDB_FLAG_MOD_ADD;
1184
1185         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1186         if (ret != LDB_SUCCESS) {
1187                 ldb_asprintf_errstring(ldb,
1188                                        "rootdse_enable_recycle_bin: Failed to modify object %s - %s",
1189                                        ldb_dn_get_linearized(ntds_settings_dn),
1190                                        ldb_errstring(ldb));
1191                 talloc_free(tmp_ctx);
1192                 return ret;
1193         }
1194
1195         msg->dn = op_feature_scope_dn;
1196         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1197         if (ret != LDB_SUCCESS) {
1198                 ldb_asprintf_errstring(ldb,
1199                                        "rootdse_enable_recycle_bin: Failed to modify object %s - %s",
1200                                        ldb_dn_get_linearized(op_feature_scope_dn),
1201                                        ldb_errstring(ldb));
1202                 talloc_free(tmp_ctx);
1203                 return ret;
1204         }
1205
1206         return LDB_SUCCESS;
1207 }
1208
1209 static int rootdse_enableoptionalfeature(struct ldb_module *module, struct ldb_request *req)
1210 {
1211         /*
1212           steps:
1213                - check for system (only system can enable features)
1214                - extract GUID from the request
1215                - find the feature object
1216                - check functional level, must be at least msDS-RequiredForestBehaviorVersion
1217                - check if it is already enabled (if enabled return LDAP_ATTRIBUTE_OR_VALUE_EXISTS) - probably not needed, just return error from the add/modify
1218                - add/modify objects (see ntdsconnection code for an example)
1219          */
1220
1221         struct ldb_context *ldb = ldb_module_get_ctx(module);
1222         struct GUID op_feature_guid;
1223         struct ldb_dn *op_feature_scope_dn;
1224         struct ldb_message *op_feature_msg;
1225         struct auth_session_info *session_info =
1226                                 (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
1227         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1228         int ret;
1229         const char *guid_string;
1230
1231         if (security_session_user_level(session_info, NULL) != SECURITY_SYSTEM) {
1232                 ldb_set_errstring(ldb, "rootdse: Insufficient rights for enableoptionalfeature");
1233                 return LDB_ERR_UNWILLING_TO_PERFORM;
1234         }
1235
1236         ret = get_optional_feature_dn_guid(req, ldb, tmp_ctx, &op_feature_scope_dn, &op_feature_guid);
1237         if (ret != LDB_SUCCESS) {
1238                 talloc_free(tmp_ctx);
1239                 return ret;
1240         }
1241
1242         guid_string = GUID_string(tmp_ctx, &op_feature_guid);
1243         if (!guid_string) {
1244                 ldb_set_errstring(ldb, "rootdse: bad optional feature GUID");
1245                 return LDB_ERR_UNWILLING_TO_PERFORM;
1246         }
1247
1248         ret = dsdb_find_optional_feature(module, ldb, tmp_ctx, op_feature_guid, &op_feature_msg, req);
1249         if (ret != LDB_SUCCESS) {
1250                 ldb_asprintf_errstring(ldb,
1251                                        "rootdse: unable to find optional feature for %s - %s",
1252                                        guid_string, ldb_errstring(ldb));
1253                 talloc_free(tmp_ctx);
1254                 return ret;
1255         }
1256
1257         if (strcasecmp(DS_GUID_FEATURE_RECYCLE_BIN, guid_string) == 0) {
1258                         ret = rootdse_enable_recycle_bin(module, ldb,
1259                                                          tmp_ctx, op_feature_scope_dn,
1260                                                          op_feature_msg, req);
1261         } else {
1262                 ldb_asprintf_errstring(ldb,
1263                                        "rootdse: unknown optional feature %s",
1264                                        guid_string);
1265                 talloc_free(tmp_ctx);
1266                 return LDB_ERR_UNWILLING_TO_PERFORM;
1267         }
1268         if (ret != LDB_SUCCESS) {
1269                 ldb_asprintf_errstring(ldb,
1270                                        "rootdse: failed to set optional feature for %s - %s",
1271                                        guid_string, ldb_errstring(ldb));
1272                 talloc_free(tmp_ctx);
1273                 return ret;
1274         }
1275
1276         talloc_free(tmp_ctx);
1277         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);;
1278 }
1279
1280 static int rootdse_schemaupdatenow(struct ldb_module *module, struct ldb_request *req)
1281 {
1282         struct ldb_context *ldb = ldb_module_get_ctx(module);
1283         struct ldb_result *ext_res;
1284         int ret;
1285         struct ldb_dn *schema_dn;
1286
1287         schema_dn = ldb_get_schema_basedn(ldb);
1288         if (!schema_dn) {
1289                 ldb_reset_err_string(ldb);
1290                 ldb_debug(ldb, LDB_DEBUG_WARNING,
1291                           "rootdse_modify: no schema dn present: (skip ldb_extended call)\n");
1292                 return ldb_next_request(module, req);
1293         }
1294
1295         ret = ldb_extended(ldb, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID, schema_dn, &ext_res);
1296         if (ret != LDB_SUCCESS) {
1297                 return ldb_operr(ldb);
1298         }
1299
1300         talloc_free(ext_res);
1301         return ldb_module_done(req, NULL, NULL, ret);
1302 }
1303
1304 static int rootdse_schemaupgradeinprogress(struct ldb_module *module, struct ldb_request *req)
1305 {
1306         struct ldb_context *ldb = ldb_module_get_ctx(module);
1307         int ret = LDB_SUCCESS;
1308         struct ldb_dn *schema_dn;
1309
1310         schema_dn = ldb_get_schema_basedn(ldb);
1311         if (!schema_dn) {
1312                 ldb_reset_err_string(ldb);
1313                 ldb_debug(ldb, LDB_DEBUG_WARNING,
1314                           "rootdse_modify: no schema dn present: (skip ldb_extended call)\n");
1315                 return ldb_next_request(module, req);
1316         }
1317
1318         /* FIXME we have to do something in order to relax constraints for DRS
1319          * setting schemaUpgradeInProgress cause the fschemaUpgradeInProgress
1320          * in all LDAP connection (2K3/2K3R2) or in the current connection (2K8 and +)
1321          * to be set to true.
1322          */
1323
1324         /* from 5.113 LDAPConnections in DRSR.pdf
1325          * fschemaUpgradeInProgress: A Boolean that specifies certain constraint
1326          * validations are skipped when adding, updating, or removing directory
1327          * objects on the opened connection. The skipped constraint validations
1328          * are documented in the applicable constraint sections in [MS-ADTS].
1329          */
1330         return ldb_module_done(req, NULL, NULL, ret);
1331 }
1332
1333 static int rootdse_add(struct ldb_module *module, struct ldb_request *req)
1334 {
1335         struct ldb_context *ldb = ldb_module_get_ctx(module);
1336         int ret;
1337
1338         ret = rootdse_filter_operations(module, req);
1339         if (ret != LDB_SUCCESS) {
1340                 return ret;
1341         }
1342
1343         ret = rootdse_filter_controls(module, req);
1344         if (ret != LDB_SUCCESS) {
1345                 return ret;
1346         }
1347
1348         /*
1349                 If dn is not "" we should let it pass through
1350         */
1351         if (!ldb_dn_is_null(req->op.add.message->dn)) {
1352                 return ldb_next_request(module, req);
1353         }
1354
1355         ldb_set_errstring(ldb, "rootdse_add: you cannot add a new rootdse entry!");
1356         return LDB_ERR_NAMING_VIOLATION;
1357 }
1358
1359 struct fsmo_transfer_state {
1360         struct ldb_context *ldb;
1361         struct ldb_request *req;
1362         struct ldb_module *module;
1363 };
1364
1365 /*
1366   called when a FSMO transfer operation has completed
1367  */
1368 static void rootdse_fsmo_transfer_callback(struct tevent_req *treq)
1369 {
1370         struct fsmo_transfer_state *fsmo = tevent_req_callback_data(treq, struct fsmo_transfer_state);
1371         NTSTATUS status;
1372         WERROR werr;
1373         int ret;
1374         struct ldb_request *req = fsmo->req;
1375         struct ldb_context *ldb = fsmo->ldb;
1376         struct ldb_module *module = fsmo->module;
1377
1378         status = dcerpc_drepl_takeFSMORole_recv(treq, fsmo, &werr);
1379         talloc_free(fsmo);
1380         if (!NT_STATUS_IS_OK(status)) {
1381                 ldb_asprintf_errstring(ldb, "Failed FSMO transfer: %s", nt_errstr(status));
1382                 /*
1383                  * Now that it is failed, start the transaction up
1384                  * again so the wrappers can close it without additional error
1385                  */
1386                 ldb_next_start_trans(module);
1387                 ldb_module_done(req, NULL, NULL, LDB_ERR_UNAVAILABLE);
1388                 return;
1389         }
1390         if (!W_ERROR_IS_OK(werr)) {
1391                 ldb_asprintf_errstring(ldb, "Failed FSMO transfer: %s", win_errstr(werr));
1392                 /*
1393                  * Now that it is failed, start the transaction up
1394                  * again so the wrappers can close it without additional error
1395                  */
1396                 ldb_next_start_trans(module);
1397                 ldb_module_done(req, NULL, NULL, LDB_ERR_UNAVAILABLE);
1398                 return;
1399         }
1400
1401         /*
1402          * Now that it is done, start the transaction up again so the
1403          * wrappers can close it without error
1404          */
1405         ret = ldb_next_start_trans(module);
1406         ldb_module_done(req, NULL, NULL, ret);
1407 }
1408
1409 static int rootdse_become_master(struct ldb_module *module,
1410                                  struct ldb_request *req,
1411                                  enum drepl_role_master role)
1412 {
1413         struct imessaging_context *msg;
1414         struct ldb_context *ldb = ldb_module_get_ctx(module);
1415         TALLOC_CTX *tmp_ctx = talloc_new(req);
1416         struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm");
1417         bool am_rodc;
1418         struct dcerpc_binding_handle *irpc_handle;
1419         int ret;
1420         struct auth_session_info *session_info;
1421         enum security_user_level level;
1422         struct fsmo_transfer_state *fsmo;
1423         struct tevent_req *treq;
1424
1425         session_info = (struct auth_session_info *)ldb_get_opaque(ldb_module_get_ctx(module), "sessionInfo");
1426         level = security_session_user_level(session_info, NULL);
1427         if (level < SECURITY_ADMINISTRATOR) {
1428                 return ldb_error(ldb, LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS, "Denied rootDSE modify for non-administrator");
1429         }
1430
1431         ret = samdb_rodc(ldb, &am_rodc);
1432         if (ret != LDB_SUCCESS) {
1433                 return ldb_error(ldb, ret, "Could not determine if server is RODC.");
1434         }
1435
1436         if (am_rodc) {
1437                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM,
1438                                  "RODC cannot become a role master.");
1439         }
1440
1441         /*
1442          * We always delete the transaction, not commit it, because
1443          * this gives the least supprise to this supprising action (as
1444          * we will never record anything done to this point
1445          */
1446         ldb_next_del_trans(module);
1447
1448         msg = imessaging_client_init(tmp_ctx, lp_ctx,
1449                                     ldb_get_event_context(ldb));
1450         if (!msg) {
1451                 ldb_asprintf_errstring(ldb, "Failed to generate client messaging context in %s", lpcfg_imessaging_path(tmp_ctx, lp_ctx));
1452                 return LDB_ERR_OPERATIONS_ERROR;
1453         }
1454         irpc_handle = irpc_binding_handle_by_name(tmp_ctx, msg,
1455                                                   "dreplsrv",
1456                                                   &ndr_table_irpc);
1457         if (irpc_handle == NULL) {
1458                 return ldb_oom(ldb);
1459         }
1460         fsmo = talloc_zero(req, struct fsmo_transfer_state);
1461         if (fsmo == NULL) {
1462                 return ldb_oom(ldb);
1463         }
1464         fsmo->ldb = ldb;
1465         fsmo->req = req;
1466         fsmo->module = module;
1467
1468         /*
1469          * we send the call asynchronously, as the ldap client is
1470          * expecting to get an error back if the role transfer fails
1471          *
1472          * We need more than the default 10 seconds IRPC allows, so
1473          * set a longer timeout (default ldb timeout is 300 seconds).
1474          * We send an async reply when we are done.
1475          *
1476          * We are the first module, so don't bother working out how
1477          * long we have spent so far.
1478          */
1479         dcerpc_binding_handle_set_timeout(irpc_handle, req->timeout);
1480
1481         treq = dcerpc_drepl_takeFSMORole_send(req, ldb_get_event_context(ldb), irpc_handle, role);
1482         if (treq == NULL) {
1483                 return ldb_oom(ldb);
1484         }
1485
1486         tevent_req_set_callback(treq, rootdse_fsmo_transfer_callback, fsmo);
1487         return LDB_SUCCESS;
1488 }
1489
1490 static int rootdse_modify(struct ldb_module *module, struct ldb_request *req)
1491 {
1492         struct ldb_context *ldb = ldb_module_get_ctx(module);
1493         int ret;
1494
1495         ret = rootdse_filter_operations(module, req);
1496         if (ret != LDB_SUCCESS) {
1497                 return ret;
1498         }
1499
1500         ret = rootdse_filter_controls(module, req);
1501         if (ret != LDB_SUCCESS) {
1502                 return ret;
1503         }
1504
1505         /*
1506                 If dn is not "" we should let it pass through
1507         */
1508         if (!ldb_dn_is_null(req->op.mod.message->dn)) {
1509                 return ldb_next_request(module, req);
1510         }
1511
1512         /*
1513                 dn is empty so check for schemaUpdateNow attribute
1514                 "The type of modification and values specified in the LDAP modify operation do not matter." MSDN
1515         */
1516         if (ldb_msg_find_element(req->op.mod.message, "schemaUpdateNow")) {
1517                 return rootdse_schemaupdatenow(module, req);
1518         }
1519         if (ldb_msg_find_element(req->op.mod.message, "becomeDomainMaster")) {
1520                 return rootdse_become_master(module, req, DREPL_NAMING_MASTER);
1521         }
1522         if (ldb_msg_find_element(req->op.mod.message, "becomeInfrastructureMaster")) {
1523                 return rootdse_become_master(module, req, DREPL_INFRASTRUCTURE_MASTER);
1524         }
1525         if (ldb_msg_find_element(req->op.mod.message, "becomeRidMaster")) {
1526                 return rootdse_become_master(module, req, DREPL_RID_MASTER);
1527         }
1528         if (ldb_msg_find_element(req->op.mod.message, "becomeSchemaMaster")) {
1529                 return rootdse_become_master(module, req, DREPL_SCHEMA_MASTER);
1530         }
1531         if (ldb_msg_find_element(req->op.mod.message, "becomePdc")) {
1532                 return rootdse_become_master(module, req, DREPL_PDC_MASTER);
1533         }
1534         if (ldb_msg_find_element(req->op.mod.message, "enableOptionalFeature")) {
1535                 return rootdse_enableoptionalfeature(module, req);
1536         }
1537         if (ldb_msg_find_element(req->op.mod.message, "schemaUpgradeInProgress")) {
1538                 return rootdse_schemaupgradeinprogress(module, req);
1539         }
1540
1541         ldb_set_errstring(ldb, "rootdse_modify: unknown attribute to change!");
1542         return LDB_ERR_UNWILLING_TO_PERFORM;
1543 }
1544
1545 static int rootdse_rename(struct ldb_module *module, struct ldb_request *req)
1546 {
1547         struct ldb_context *ldb = ldb_module_get_ctx(module);
1548         int ret;
1549
1550         ret = rootdse_filter_operations(module, req);
1551         if (ret != LDB_SUCCESS) {
1552                 return ret;
1553         }
1554
1555         ret = rootdse_filter_controls(module, req);
1556         if (ret != LDB_SUCCESS) {
1557                 return ret;
1558         }
1559
1560         /*
1561                 If dn is not "" we should let it pass through
1562         */
1563         if (!ldb_dn_is_null(req->op.rename.olddn)) {
1564                 return ldb_next_request(module, req);
1565         }
1566
1567         ldb_set_errstring(ldb, "rootdse_remove: you cannot rename the rootdse entry!");
1568         return LDB_ERR_NO_SUCH_OBJECT;
1569 }
1570
1571 static int rootdse_delete(struct ldb_module *module, struct ldb_request *req)
1572 {
1573         struct ldb_context *ldb = ldb_module_get_ctx(module);
1574         int ret;
1575
1576         ret = rootdse_filter_operations(module, req);
1577         if (ret != LDB_SUCCESS) {
1578                 return ret;
1579         }
1580
1581         ret = rootdse_filter_controls(module, req);
1582         if (ret != LDB_SUCCESS) {
1583                 return ret;
1584         }
1585
1586         /*
1587                 If dn is not "" we should let it pass through
1588         */
1589         if (!ldb_dn_is_null(req->op.del.dn)) {
1590                 return ldb_next_request(module, req);
1591         }
1592
1593         ldb_set_errstring(ldb, "rootdse_remove: you cannot delete the rootdse entry!");
1594         return LDB_ERR_NO_SUCH_OBJECT;
1595 }
1596
1597 static int rootdse_extended(struct ldb_module *module, struct ldb_request *req)
1598 {
1599         int ret;
1600
1601         ret = rootdse_filter_operations(module, req);
1602         if (ret != LDB_SUCCESS) {
1603                 return ret;
1604         }
1605
1606         ret = rootdse_filter_controls(module, req);
1607         if (ret != LDB_SUCCESS) {
1608                 return ret;
1609         }
1610
1611         return ldb_next_request(module, req);
1612 }
1613
1614 static const struct ldb_module_ops ldb_rootdse_module_ops = {
1615         .name           = "rootdse",
1616         .init_context   = rootdse_init,
1617         .search         = rootdse_search,
1618         .request        = rootdse_request,
1619         .add            = rootdse_add,
1620         .modify         = rootdse_modify,
1621         .rename         = rootdse_rename,
1622         .extended       = rootdse_extended,
1623         .del            = rootdse_delete
1624 };
1625
1626 int ldb_rootdse_module_init(const char *version)
1627 {
1628         LDB_MODULE_CHECK_VERSION(version);
1629         return ldb_register_module(&ldb_rootdse_module_ops);
1630 }