s4-drs: added new SECURITY_RO_DOMAIN_CONTROLLER level
[samba.git] / source4 / dsdb / samdb / ldb_modules / kludge_acl.c
index 275e9b5299c9600c3151bfe05a69446284824c53..42f0a306f43e34f731f0bc84072d5f7b3ea5f28d 100644 (file)
  */
 
 #include "includes.h"
-#include "ldb/include/ldb.h"
-#include "ldb/include/ldb_errors.h"
-#include "ldb/include/ldb_private.h"
+#include "ldb_module.h"
 #include "auth/auth.h"
 #include "libcli/security/security.h"
 #include "dsdb/samdb/samdb.h"
+#include "param/param.h"
+#include "lib/util/tsort.h"
 
 /* Kludge ACL rules:
  *
 
 struct kludge_private_data {
        const char **password_attrs;
+       bool acl_perform;
 };
 
 static enum security_user_level what_is_user(struct ldb_module *module) 
 {
+       struct ldb_context *ldb = ldb_module_get_ctx(module);
        struct auth_session_info *session_info
-               = (struct auth_session_info *)ldb_get_opaque(module->ldb, "sessionInfo");
-       return security_session_user_level(session_info);
+               = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
+       return security_session_user_level(session_info, NULL);
 }
 
 static const char *user_name(TALLOC_CTX *mem_ctx, struct ldb_module *module) 
 {
+       struct ldb_context *ldb = ldb_module_get_ctx(module);
        struct auth_session_info *session_info
-               = (struct auth_session_info *)ldb_get_opaque(module->ldb, "sessionInfo");
+               = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
        if (!session_info) {
                return "UNKNOWN (NULL)";
        }
@@ -91,10 +94,12 @@ static int kludge_acl_allowedAttributes(struct ldb_context *ldb, struct ldb_mess
 {
        struct ldb_message_element *oc_el;
        struct ldb_message_element *allowedAttributes;
-       const struct dsdb_schema *schema = dsdb_get_schema(ldb);
+       /* We need to ensure that the strings returned are valid for as long as the msg is valid */
+       const struct dsdb_schema *schema = dsdb_get_schema(ldb, msg);
        TALLOC_CTX *mem_ctx;
-       char **objectclass_list, **attr_list;
-       int i, ret;
+       const char **attr_list;
+       unsigned int i;
+       int ret;
 
        /* If we don't have a schema yet, we can't do anything... */
        if (schema == NULL) {
@@ -118,19 +123,7 @@ static int kludge_acl_allowedAttributes(struct ldb_context *ldb, struct ldb_mess
           we alter the element array in ldb_msg_add_empty() */
        oc_el = ldb_msg_find_element(msg, "objectClass");
        
-       objectclass_list = talloc_array(mem_ctx, char *, oc_el->num_values + 1);
-       if (!objectclass_list) {
-               ldb_oom(ldb);
-               talloc_free(mem_ctx);
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
-       for (i=0; oc_el && i < oc_el->num_values; i++) {
-               objectclass_list[i] = (char *)oc_el->values[i].data;
-       }
-       objectclass_list[i] = NULL;
-
-       attr_list = dsdb_full_attribute_list(mem_ctx, schema, (const char **)objectclass_list, DSDB_SCHEMA_ALL);
+       attr_list = dsdb_full_attribute_list(mem_ctx, schema, oc_el, DSDB_SCHEMA_ALL);
        if (!attr_list) {
                ldb_asprintf_errstring(ldb, "kludge_acl: Failed to get list of attributes create %s attribute", attrName);
                talloc_free(mem_ctx);
@@ -151,9 +144,12 @@ static int kludge_acl_childClasses(struct ldb_context *ldb, struct ldb_message *
 {
        struct ldb_message_element *oc_el;
        struct ldb_message_element *allowedClasses;
-       const struct dsdb_schema *schema = dsdb_get_schema(ldb);
-       const struct dsdb_class *class;
-       int i, j, ret;
+
+       /* We need to ensure that the strings returned are valid for as long as the msg is valid */
+       const struct dsdb_schema *schema = dsdb_get_schema(ldb, msg);
+       const struct dsdb_class *sclass;
+       unsigned int i, j;
+       int ret;
 
        /* If we don't have a schema yet, we can't do anything... */
        if (schema == NULL) {
@@ -172,22 +168,19 @@ static int kludge_acl_childClasses(struct ldb_context *ldb, struct ldb_message *
        oc_el = ldb_msg_find_element(msg, "objectClass");
 
        for (i=0; oc_el && i < oc_el->num_values; i++) {
-               class = dsdb_class_by_lDAPDisplayName(schema, (const char *)oc_el->values[i].data);
-               if (!class) {
+               sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]);
+               if (!sclass) {
                        /* We don't know this class?  what is going on? */
                        continue;
                }
 
-               for (j=0; class->possibleInferiors && class->possibleInferiors[j]; j++) {
-                       ldb_msg_add_string(msg, attrName, class->possibleInferiors[j]);
+               for (j=0; sclass->possibleInferiors && sclass->possibleInferiors[j]; j++) {
+                       ldb_msg_add_string(msg, attrName, sclass->possibleInferiors[j]);
                }
        }
                
        if (allowedClasses->num_values > 1) {
-               qsort(allowedClasses->values, 
-                     allowedClasses->num_values, 
-                     sizeof(*allowedClasses->values),
-                     (comparison_fn_t)data_blob_cmp);
+               TYPESAFE_QSORT(allowedClasses->values, allowedClasses->num_values, data_blob_cmp);
        
                for (i=1 ; i < allowedClasses->num_values; i++) {
 
@@ -202,19 +195,21 @@ static int kludge_acl_childClasses(struct ldb_context *ldb, struct ldb_message *
        }
 
        return LDB_SUCCESS;
-
 }
 
 /* find all attributes allowed by all these objectClasses */
 
 static int kludge_acl_callback(struct ldb_request *req, struct ldb_reply *ares)
 {
+       struct ldb_context *ldb;
        struct kludge_acl_context *ac;
        struct kludge_private_data *data;
-       int i, ret;
+       unsigned int i;
+       int ret;
 
        ac = talloc_get_type(req->context, struct kludge_acl_context);
-       data = talloc_get_type(ac->module->private_data, struct kludge_private_data);
+       data = talloc_get_type(ldb_module_get_private(ac->module), struct kludge_private_data);
+       ldb = ldb_module_get_ctx(ac->module);
 
        if (!ares) {
                return ldb_module_done(ac->req, NULL, NULL,
@@ -228,7 +223,7 @@ static int kludge_acl_callback(struct ldb_request *req, struct ldb_reply *ares)
        switch (ares->type) {
        case LDB_REPLY_ENTRY:
                if (ac->allowedAttributes) {
-                       ret = kludge_acl_allowedAttributes(ac->module->ldb,
+                       ret = kludge_acl_allowedAttributes(ldb,
                                                   ares->message,
                                                   "allowedAttributes");
                        if (ret != LDB_SUCCESS) {
@@ -236,7 +231,7 @@ static int kludge_acl_callback(struct ldb_request *req, struct ldb_reply *ares)
                        }
                }
                if (ac->allowedChildClasses) {
-                       ret = kludge_acl_childClasses(ac->module->ldb,
+                       ret = kludge_acl_childClasses(ldb,
                                                ares->message,
                                                "allowedChildClasses");
                        if (ret != LDB_SUCCESS) {
@@ -249,14 +244,14 @@ static int kludge_acl_callback(struct ldb_request *req, struct ldb_reply *ares)
                        switch (ac->user_type) {
                        case SECURITY_SYSTEM:
                                if (ac->allowedAttributesEffective) {
-                                       ret = kludge_acl_allowedAttributes(ac->module->ldb, ares->message,
+                                       ret = kludge_acl_allowedAttributes(ldb, ares->message,
                                                                        "allowedAttributesEffective");
                                        if (ret != LDB_SUCCESS) {
                                                return ldb_module_done(ac->req, NULL, NULL, ret);
                                        }
                                }
                                if (ac->allowedChildClassesEffective) {
-                                       ret = kludge_acl_childClasses(ac->module->ldb, ares->message,
+                                       ret = kludge_acl_childClasses(ldb, ares->message,
                                                                        "allowedChildClassesEffective");
                                        if (ret != LDB_SUCCESS) {
                                                return ldb_module_done(ac->req, NULL, NULL, ret);
@@ -266,14 +261,14 @@ static int kludge_acl_callback(struct ldb_request *req, struct ldb_reply *ares)
 
                        case SECURITY_ADMINISTRATOR:
                                if (ac->allowedAttributesEffective) {
-                                       ret = kludge_acl_allowedAttributes(ac->module->ldb, ares->message,
+                                       ret = kludge_acl_allowedAttributes(ldb, ares->message,
                                                                        "allowedAttributesEffective");
                                        if (ret != LDB_SUCCESS) {
                                                return ldb_module_done(ac->req, NULL, NULL, ret);
                                        }
                                }
                                if (ac->allowedChildClassesEffective) {
-                                       ret = kludge_acl_childClasses(ac->module->ldb, ares->message,
+                                       ret = kludge_acl_childClasses(ldb, ares->message,
                                                                        "allowedChildClassesEffective");
                                        if (ret != LDB_SUCCESS) {
                                                return ldb_module_done(ac->req, NULL, NULL, ret);
@@ -316,21 +311,26 @@ static int kludge_acl_callback(struct ldb_request *req, struct ldb_reply *ares)
 
 static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req)
 {
+       struct ldb_context *ldb;
        struct kludge_acl_context *ac;
        struct ldb_request *down_req;
        struct kludge_private_data *data;
        const char * const *attrs;
-       int ret, i;
-       struct ldb_control *sd_control;
-       struct ldb_control **sd_saved_controls;
+       int ret;
+       unsigned int i;
+
+       ldb = ldb_module_get_ctx(module);
 
        ac = talloc(req, struct kludge_acl_context);
        if (ac == NULL) {
-               ldb_oom(module->ldb);
+               ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       data = talloc_get_type(module->private_data, struct kludge_private_data);
+       data = talloc_get_type(ldb_module_get_private(module), struct kludge_private_data);
+
+       if (data && data->acl_perform)
+               return ldb_next_request(module, req);
 
        ac->module = module;
        ac->req = req;
@@ -372,7 +372,7 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req)
        }
 
        ret = ldb_build_search_req_ex(&down_req,
-                                       module->ldb, ac,
+                                       ldb, ac,
                                        req->op.search.base,
                                        req->op.search.scope,
                                        req->op.search.tree,
@@ -381,18 +381,7 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req)
                                        ac, kludge_acl_callback,
                                        req);
        if (ret != LDB_SUCCESS) {
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
-       /* check if there's an SD_FLAGS control */
-       sd_control = ldb_request_get_control(down_req, LDB_CONTROL_SD_FLAGS_OID);
-       if (sd_control) {
-               /* save it locally and remove it from the list */
-               /* we do not need to replace them later as we
-                * are keeping the original req intact */
-               if (!save_controls(sd_control, down_req, &sd_saved_controls)) {
-                       return LDB_ERR_OPERATIONS_ERROR;
-               }
+               return ret;
        }
 
        /* perform the search */
@@ -402,13 +391,20 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req)
 /* ANY change type */
 static int kludge_acl_change(struct ldb_module *module, struct ldb_request *req)
 {
+       struct ldb_context *ldb = ldb_module_get_ctx(module);
        enum security_user_level user_type = what_is_user(module);
+       struct kludge_private_data *data = talloc_get_type(ldb_module_get_private(module),
+                                                          struct kludge_private_data);
+
+       if (data->acl_perform)
+               return ldb_next_request(module, req);
+
        switch (user_type) {
        case SECURITY_SYSTEM:
        case SECURITY_ADMINISTRATOR:
                return ldb_next_request(module, req);
        default:
-               ldb_asprintf_errstring(module->ldb,
+               ldb_asprintf_errstring(ldb,
                                       "kludge_acl_change: "
                                       "attempted database modify not permitted. "
                                       "User %s is not SYSTEM or an administrator",
@@ -419,6 +415,7 @@ static int kludge_acl_change(struct ldb_module *module, struct ldb_request *req)
 
 static int kludge_acl_extended(struct ldb_module *module, struct ldb_request *req)
 {
+       struct ldb_context *ldb = ldb_module_get_ctx(module);
        enum security_user_level user_type;
 
        /* allow everybody to read the sequence number */
@@ -434,7 +431,7 @@ static int kludge_acl_extended(struct ldb_module *module, struct ldb_request *re
        case SECURITY_ADMINISTRATOR:
                return ldb_next_request(module, req);
        default:
-               ldb_asprintf_errstring(module->ldb,
+               ldb_asprintf_errstring(ldb,
                                       "kludge_acl_change: "
                                       "attempted database modify not permitted. "
                                       "User %s is not SYSTEM or an administrator",
@@ -445,7 +442,9 @@ static int kludge_acl_extended(struct ldb_module *module, struct ldb_request *re
 
 static int kludge_acl_init(struct ldb_module *module)
 {
-       int ret, i;
+       struct ldb_context *ldb;
+       int ret;
+       unsigned int i;
        TALLOC_CTX *mem_ctx = talloc_new(module);
        static const char *attrs[] = { "passwordAttribute", NULL };
        struct ldb_result *res;
@@ -454,22 +453,26 @@ static int kludge_acl_init(struct ldb_module *module)
 
        struct kludge_private_data *data;
 
+       ldb = ldb_module_get_ctx(module);
+
        data = talloc(module, struct kludge_private_data);
        if (data == NULL) {
-               ldb_oom(module->ldb);
+               ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
        data->password_attrs = NULL;
-       module->private_data = data;
+       data->acl_perform = lp_parm_bool(ldb_get_opaque(ldb, "loadparm"),
+                                        NULL, "acl", "perform", false);
+       ldb_module_set_private(module, data);
 
        if (!mem_ctx) {
-               ldb_oom(module->ldb);
+               ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       ret = ldb_search(module->ldb, mem_ctx, &res,
-                        ldb_dn_new(mem_ctx, module->ldb, "@KLUDGEACL"),
+       ret = ldb_search(ldb, mem_ctx, &res,
+                        ldb_dn_new(mem_ctx, ldb, "@KLUDGEACL"),
                         LDB_SCOPE_BASE, attrs, NULL);
        if (ret != LDB_SUCCESS) {
                goto done;
@@ -492,7 +495,7 @@ static int kludge_acl_init(struct ldb_module *module)
        data->password_attrs = talloc_array(data, const char *, password_attributes->num_values + 1);
        if (!data->password_attrs) {
                talloc_free(mem_ctx);
-               ldb_oom(module->ldb);
+               ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
        }
        for (i=0; i < password_attributes->num_values; i++) {
@@ -501,13 +504,6 @@ static int kludge_acl_init(struct ldb_module *module)
        }
        data->password_attrs[i] = NULL;
 
-       ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
-       if (ret != LDB_SUCCESS) {
-               ldb_debug(module->ldb, LDB_DEBUG_ERROR,
-                       "partition: Unable to register control with rootdse!\n");
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
 done:
        talloc_free(mem_ctx);
        return ldb_next_init(module);
@@ -515,11 +511,11 @@ done:
 
 _PUBLIC_ const struct ldb_module_ops ldb_kludge_acl_module_ops = {
        .name              = "kludge_acl",
-       .search            = kludge_acl_search,
+/*     .search            = kludge_acl_search, 
        .add               = kludge_acl_change,
        .modify            = kludge_acl_change,
        .del               = kludge_acl_change,
-       .rename            = kludge_acl_change,
+       .rename            = kludge_acl_change, */
        .extended          = kludge_acl_extended,
        .init_context      = kludge_acl_init
 };