diff options
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/kludge_acl.c | 516 |
1 files changed, 0 insertions, 516 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/kludge_acl.c b/source4/dsdb/samdb/ldb_modules/kludge_acl.c deleted file mode 100644 index e6f288d01c..0000000000 --- a/source4/dsdb/samdb/ldb_modules/kludge_acl.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - ldb database library - - Copyright (C) Andrew Bartlett 2005 - Copyright (C) Simo Sorce 2006-2008 - - 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - 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, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Name: ldb - * - * Component: ldb kludge ACL module - * - * Description: Simple module to enforce a simple form of access - * control, sufficient for securing a default Samba4 - * installation. - * - * Author: Andrew Bartlett - */ - -#include "includes.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: - * - * - System can read passwords - * - Administrators can write anything - * - Users can read anything that is not a password - * - */ - -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(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(ldb, "sessionInfo"); - if (!session_info) { - return "UNKNOWN (NULL)"; - } - - return talloc_asprintf(mem_ctx, "%s\\%s", - session_info->server_info->domain_name, - session_info->server_info->account_name); -} - -/* search */ -struct kludge_acl_context { - - struct ldb_module *module; - struct ldb_request *req; - - enum security_user_level user_type; - bool allowedAttributes; - bool allowedAttributesEffective; - bool allowedChildClasses; - bool allowedChildClassesEffective; - const char * const *attrs; -}; - -/* read all objectClasses */ - -static int kludge_acl_allowedAttributes(struct ldb_context *ldb, struct ldb_message *msg, - const char *attrName) -{ - struct ldb_message_element *oc_el; - struct ldb_message_element *allowedAttributes; - /* 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; - 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) { - return LDB_SUCCESS; - } - - /* Must remove any existing attribute, or else confusion reins */ - ldb_msg_remove_attr(msg, attrName); - ret = ldb_msg_add_empty(msg, attrName, 0, &allowedAttributes); - if (ret != LDB_SUCCESS) { - return ret; - } - - mem_ctx = talloc_new(msg); - if (!mem_ctx) { - return ldb_oom(ldb); - } - - /* To ensure that oc_el is valid, we must look for it after - we alter the element array in ldb_msg_add_empty() */ - oc_el = ldb_msg_find_element(msg, "objectClass"); - - 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); - return LDB_ERR_OPERATIONS_ERROR; - } - - for (i=0; attr_list && attr_list[i]; i++) { - ldb_msg_add_string(msg, attrName, attr_list[i]); - } - talloc_free(mem_ctx); - return LDB_SUCCESS; - -} -/* read all objectClasses */ - -static int kludge_acl_childClasses(struct ldb_context *ldb, struct ldb_message *msg, - const char *attrName) -{ - struct ldb_message_element *oc_el; - struct ldb_message_element *allowedClasses; - - /* 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) { - return LDB_SUCCESS; - } - - /* Must remove any existing attribute, or else confusion reins */ - ldb_msg_remove_attr(msg, attrName); - ret = ldb_msg_add_empty(msg, attrName, 0, &allowedClasses); - if (ret != LDB_SUCCESS) { - return ret; - } - - /* To ensure that oc_el is valid, we must look for it after - we alter the element array in ldb_msg_add_empty() */ - oc_el = ldb_msg_find_element(msg, "objectClass"); - - for (i=0; oc_el && i < oc_el->num_values; i++) { - 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; sclass->possibleInferiors && sclass->possibleInferiors[j]; j++) { - ldb_msg_add_string(msg, attrName, sclass->possibleInferiors[j]); - } - } - - if (allowedClasses->num_values > 1) { - TYPESAFE_QSORT(allowedClasses->values, allowedClasses->num_values, data_blob_cmp); - - for (i=1 ; i < allowedClasses->num_values; i++) { - - struct ldb_val *val1 = &allowedClasses->values[i-1]; - struct ldb_val *val2 = &allowedClasses->values[i]; - if (data_blob_cmp(val1, val2) == 0) { - memmove(val1, val2, (allowedClasses->num_values - i) * sizeof( struct ldb_val)); - allowedClasses->num_values--; - i--; - } - } - } - - 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; - unsigned int i; - int ret; - - ac = talloc_get_type(req->context, struct kludge_acl_context); - 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, - LDB_ERR_OPERATIONS_ERROR); - } - if (ares->error != LDB_SUCCESS) { - return ldb_module_done(ac->req, ares->controls, - ares->response, ares->error); - } - - switch (ares->type) { - case LDB_REPLY_ENTRY: - if (ac->allowedAttributes) { - ret = kludge_acl_allowedAttributes(ldb, - ares->message, - "allowedAttributes"); - if (ret != LDB_SUCCESS) { - return ldb_module_done(ac->req, NULL, NULL, ret); - } - } - if (ac->allowedChildClasses) { - ret = kludge_acl_childClasses(ldb, - ares->message, - "allowedChildClasses"); - if (ret != LDB_SUCCESS) { - return ldb_module_done(ac->req, NULL, NULL, ret); - } - } - - if (data && data->password_attrs) /* if we are not initialized just get through */ - { - switch (ac->user_type) { - case SECURITY_SYSTEM: - if (ac->allowedAttributesEffective) { - 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(ldb, ares->message, - "allowedChildClassesEffective"); - if (ret != LDB_SUCCESS) { - return ldb_module_done(ac->req, NULL, NULL, ret); - } - } - break; - - case SECURITY_ADMINISTRATOR: - if (ac->allowedAttributesEffective) { - 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(ldb, ares->message, - "allowedChildClassesEffective"); - if (ret != LDB_SUCCESS) { - return ldb_module_done(ac->req, NULL, NULL, ret); - } - } - /* fall through */ - default: - /* remove password attributes */ - for (i = 0; data->password_attrs[i]; i++) { - ldb_msg_remove_attr(ares->message, data->password_attrs[i]); - } - } - } - - if (ac->allowedAttributes || - ac->allowedAttributesEffective || - ac->allowedChildClasses || - ac->allowedChildClassesEffective) { - - if (!ldb_attr_in_list(ac->attrs, "objectClass") && - !ldb_attr_in_list(ac->attrs, "*")) { - - ldb_msg_remove_attr(ares->message, - "objectClass"); - } - } - - return ldb_module_send_entry(ac->req, ares->message, ares->controls); - - case LDB_REPLY_REFERRAL: - return ldb_module_send_referral(ac->req, ares->referral); - - case LDB_REPLY_DONE: - return ldb_module_done(ac->req, ares->controls, - ares->response, LDB_SUCCESS); - - } - return LDB_SUCCESS; -} - -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; - unsigned int i; - - ldb = ldb_module_get_ctx(module); - - ac = talloc(req, struct kludge_acl_context); - if (ac == NULL) { - return ldb_oom(ldb); - } - - 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; - ac->user_type = what_is_user(module); - ac->attrs = req->op.search.attrs; - - ac->allowedAttributes = ldb_attr_in_list(req->op.search.attrs, "allowedAttributes"); - - ac->allowedAttributesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedAttributesEffective"); - - ac->allowedChildClasses = ldb_attr_in_list(req->op.search.attrs, "allowedChildClasses"); - - ac->allowedChildClassesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedChildClassesEffective"); - - if (ac->allowedAttributes || ac->allowedAttributesEffective || ac->allowedChildClasses || ac->allowedChildClassesEffective) { - attrs = ldb_attr_list_copy_add(ac, req->op.search.attrs, "objectClass"); - } else { - attrs = req->op.search.attrs; - } - - /* replace any attributes in the parse tree that are private, - so we don't allow a search for 'userPassword=penguin', - just as we would not allow that attribute to be returned */ - switch (ac->user_type) { - case SECURITY_SYSTEM: - break; - default: - /* FIXME: We should copy the tree and keep the original unmodified. */ - /* remove password attributes */ - - if (!data || !data->password_attrs) { - break; - } - for (i = 0; data->password_attrs[i]; i++) { - ldb_parse_tree_attr_replace(req->op.search.tree, - data->password_attrs[i], - "kludgeACLredactedattribute"); - } - } - - ret = ldb_build_search_req_ex(&down_req, - ldb, ac, - req->op.search.base, - req->op.search.scope, - req->op.search.tree, - attrs, - req->controls, - ac, kludge_acl_callback, - req); - if (ret != LDB_SUCCESS) { - return ret; - } - - /* perform the search */ - return ldb_next_request(module, down_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(ldb, - "kludge_acl_change: " - "attempted database modify not permitted. " - "User %s is not SYSTEM or an administrator", - user_name(req, module)); - return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; - } -} - -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 */ - if (strcmp(req->op.extended.oid, - LDB_EXTENDED_SEQUENCE_NUMBER) == 0) { - return ldb_next_request(module, req); - } - - user_type = what_is_user(module); - - switch (user_type) { - case SECURITY_SYSTEM: - case SECURITY_ADMINISTRATOR: - return ldb_next_request(module, req); - default: - ldb_asprintf_errstring(ldb, - "kludge_acl_change: " - "attempted database modify not permitted. " - "User %s is not SYSTEM or an administrator", - user_name(req, module)); - return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; - } -} - -static int kludge_acl_init(struct ldb_module *module) -{ - 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; - struct ldb_message *msg; - struct ldb_message_element *password_attributes; - - struct kludge_private_data *data; - - ldb = ldb_module_get_ctx(module); - - data = talloc(module, struct kludge_private_data); - if (data == NULL) { - return ldb_oom(ldb); - } - - data->password_attrs = NULL; - data->acl_perform = lpcfg_parm_bool(ldb_get_opaque(ldb, "loadparm"), - NULL, "acl", "perform", false); - ldb_module_set_private(module, data); - - if (!mem_ctx) { - return ldb_oom(ldb); - } - - 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; - } - if (res->count == 0) { - goto done; - } - - if (res->count > 1) { - talloc_free(mem_ctx); - return LDB_ERR_CONSTRAINT_VIOLATION; - } - - msg = res->msgs[0]; - - password_attributes = ldb_msg_find_element(msg, "passwordAttribute"); - if (!password_attributes) { - goto done; - } - data->password_attrs = talloc_array(data, const char *, password_attributes->num_values + 1); - if (!data->password_attrs) { - talloc_free(mem_ctx); - return ldb_oom(ldb); - } - for (i=0; i < password_attributes->num_values; i++) { - data->password_attrs[i] = (const char *)password_attributes->values[i].data; - talloc_steal(data->password_attrs, password_attributes->values[i].data); - } - data->password_attrs[i] = NULL; - -done: - talloc_free(mem_ctx); - return ldb_next_init(module); -} - -_PUBLIC_ const struct ldb_module_ops ldb_kludge_acl_module_ops = { - .name = "kludge_acl", -/* .search = kludge_acl_search, - .add = kludge_acl_change, - .modify = kludge_acl_change, - .del = kludge_acl_change, - .rename = kludge_acl_change, */ - .extended = kludge_acl_extended, - .init_context = kludge_acl_init -}; |