Clean up provision and rootdse module to hard-code less stuff.
[samba.git] / source4 / dsdb / samdb / ldb_modules / rootdse.c
index e073c8f89bd8d656940f0f971a32c79f31502d8c..50f333d09572bfd6d70150641f748ff5be174531 100644 (file)
@@ -8,7 +8,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -17,8 +17,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -26,6 +25,8 @@
 #include "lib/ldb/include/ldb_errors.h"
 #include "lib/ldb/include/ldb_private.h"
 #include "system/time.h"
+#include "dsdb/samdb/samdb.h"
+#include "version.h"
 
 struct private_data {
        int num_controls;
@@ -44,6 +45,11 @@ static int do_attribute(const char * const *attrs, const char *name)
                ldb_attr_in_list(attrs, "*");
 }
 
+static int do_attribute_explicit(const char * const *attrs, const char *name)
+{
+       return attrs != NULL && ldb_attr_in_list(attrs, name);
+}
+
 
 /*
   add dynamically generated attributes to rootDSE result
@@ -52,6 +58,9 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms
 {
        struct private_data *priv = talloc_get_type(module->private_data, struct private_data);
        char **server_sasl;
+       const struct dsdb_schema *schema;
+
+       schema = dsdb_get_schema(module->ldb);
 
        msg->dn = ldb_dn_new(msg, module->ldb, NULL);
 
@@ -86,7 +95,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms
                for (i = 0; i < priv->num_partitions; i++) {
                        struct ldb_dn *dn = priv->partitions[i];
                        if (ldb_msg_add_steal_string(msg, "namingContexts",
-                                                    ldb_dn_linearize(msg, dn)) != 0) {
+                                                    ldb_dn_alloc_linearized(msg, dn)) != 0) {
                                goto failed;
                        }
                }
@@ -119,6 +128,88 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms
                }
        }
 
+       if (schema && do_attribute_explicit(attrs, "dsSchemaAttrCount")) {
+               struct dsdb_attribute *cur;
+               uint32_t n = 0;
+
+               for (cur = schema->attributes; cur; cur = cur->next) {
+                       n++;
+               }
+
+               if (ldb_msg_add_fmt(msg, "dsSchemaAttrCount", 
+                                   "%u", n) != 0) {
+                       goto failed;
+               }
+       }
+
+       if (schema && do_attribute_explicit(attrs, "dsSchemaClassCount")) {
+               struct dsdb_class *cur;
+               uint32_t n = 0;
+
+               for (cur = schema->classes; cur; cur = cur->next) {
+                       n++;
+               }
+
+               if (ldb_msg_add_fmt(msg, "dsSchemaClassCount", 
+                                   "%u", n) != 0) {
+                       goto failed;
+               }
+       }
+
+       if (schema && do_attribute_explicit(attrs, "dsSchemaPrefixCount")) {
+               if (ldb_msg_add_fmt(msg, "dsSchemaPrefixCount", 
+                                   "%u", schema->num_prefixes) != 0) {
+                       goto failed;
+               }
+       }
+
+       if (do_attribute_explicit(attrs, "validFSMOs")) {
+               const struct dsdb_schema_fsmo *schema_fsmo;
+               const struct dsdb_naming_fsmo *naming_fsmo;
+               const struct dsdb_pdc_fsmo *pdc_fsmo;
+               const char *dn_str;
+
+               schema_fsmo = talloc_get_type(ldb_get_opaque(module->ldb, "dsdb_schema_fsmo"),
+                                             struct dsdb_schema_fsmo);
+               if (schema_fsmo && schema_fsmo->we_are_master) {
+                       dn_str = ldb_dn_get_linearized(samdb_schema_dn(module->ldb));
+                       if (dn_str && dn_str[0]) {
+                               if (ldb_msg_add_fmt(msg, "validFSMOs", "%s", dn_str) != 0) {
+                                       goto failed;
+                               }
+                       }
+               }
+
+               naming_fsmo = talloc_get_type(ldb_get_opaque(module->ldb, "dsdb_naming_fsmo"),
+                                             struct dsdb_naming_fsmo);
+               if (naming_fsmo && naming_fsmo->we_are_master) {
+                       dn_str = ldb_dn_get_linearized(samdb_partitions_dn(module->ldb, msg));
+                       if (dn_str && dn_str[0]) {
+                               if (ldb_msg_add_fmt(msg, "validFSMOs", "%s", dn_str) != 0) {
+                                       goto failed;
+                               }
+                       }
+               }
+
+               pdc_fsmo = talloc_get_type(ldb_get_opaque(module->ldb, "dsdb_pdc_fsmo"),
+                                          struct dsdb_pdc_fsmo);
+               if (pdc_fsmo && pdc_fsmo->we_are_master) {
+                       dn_str = ldb_dn_get_linearized(samdb_base_dn(module->ldb));
+                       if (dn_str && dn_str[0]) {
+                               if (ldb_msg_add_fmt(msg, "validFSMOs", "%s", dn_str) != 0) {
+                                       goto failed;
+                               }
+                       }
+               }
+       }
+
+       if (schema && do_attribute_explicit(attrs, "vendorVersion")) {
+               if (ldb_msg_add_fmt(msg, "vendorVersion", 
+                                   "%s", SAMBA_VERSION_STRING) != 0) {
+                       goto failed;
+               }
+       }
+
        /* TODO: lots more dynamic attributes should be added here */
 
        return LDB_SUCCESS;
@@ -143,11 +234,6 @@ static int rootdse_callback(struct ldb_context *ldb, void *context, struct ldb_r
 {
        struct rootdse_context *ac;
 
-       if (!context || !ares) {
-               ldb_set_errstring(ldb, "NULL Context or Result in callback");
-               goto error;
-       }
-
        ac = talloc_get_type(context, struct rootdse_context);
 
        if (ares->type == LDB_REPLY_ENTRY) {
@@ -202,8 +288,8 @@ static int rootdse_search(struct ldb_module *module, struct ldb_request *req)
        }
 
        down_req->operation = req->operation;
-       /* in our db we store the rootDSE with a DN of cn=rootDSE */
-       down_req->op.search.base = ldb_dn_new(down_req, module->ldb, "cn=rootDSE");
+       /* in our db we store the rootDSE with a DN of @ROOTDSE */
+       down_req->op.search.base = ldb_dn_new(down_req, module->ldb, "@ROOTDSE");
        down_req->op.search.scope = LDB_SCOPE_BASE;
        down_req->op.search.tree = ldb_parse_tree(down_req, NULL);
        if (down_req->op.search.base == NULL || down_req->op.search.tree == NULL) {
@@ -303,18 +389,14 @@ static int rootdse_init(struct ldb_module *module)
        data->partitions = NULL;
        module->private_data = data;
 
+       ldb_set_default_dns(module->ldb);
+
        return ldb_next_init(module);
 }
 
-static const struct ldb_module_ops rootdse_ops = {
+_PUBLIC_ const struct ldb_module_ops ldb_rootdse_module_ops = {
        .name                   = "rootdse",
        .init_context           = rootdse_init,
        .search                 = rootdse_search,
        .request                = rootdse_request
 };
-
-int rootdse_module_init(void)
-{
-       return ldb_register_module(&rootdse_ops);
-}
-