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,
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 "ldb/include/ldb_private.h"
#include "auth/auth.h"
#include "libcli/security/security.h"
+#include "dsdb/samdb/samdb.h"
/* Kludge ACL rules:
*
int (*up_callback)(struct ldb_context *, void *, struct ldb_reply *);
enum user_is user_type;
+ bool allowedAttributes;
+ bool allowedAttributesEffective;
+ const char **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 = ldb_msg_find_element(msg, "objectClass");
+ struct ldb_message_element *allowedAttributes;
+ const struct dsdb_schema *schema = dsdb_get_schema(ldb);
+ const struct dsdb_class *class;
+ int i, j, ret;
+ ret = ldb_msg_add_empty(msg, attrName, 0, &allowedAttributes);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ for (i=0; i < oc_el->num_values; i++) {
+ class = dsdb_class_by_lDAPDisplayName(schema, (const char *)oc_el->values[i].data);
+ if (!class) {
+ /* We don't know this class? what is going on? */
+ continue;
+ }
+ for (j=0; class->mayContain && class->mayContain[j]; j++) {
+ ldb_msg_add_string(msg, attrName, class->mayContain[j]);
+ }
+ for (j=0; class->mustContain && class->mustContain[j]; j++) {
+ ldb_msg_add_string(msg, attrName, class->mustContain[j]);
+ }
+ for (j=0; class->systemMayContain && class->systemMayContain[j]; j++) {
+ ldb_msg_add_string(msg, attrName, class->systemMayContain[j]);
+ }
+ for (j=0; class->systemMustContain && class->systemMustContain[j]; j++) {
+ ldb_msg_add_string(msg, attrName, class->systemMustContain[j]);
+ }
+ }
+
+ if (allowedAttributes->num_values > 1) {
+ qsort(allowedAttributes->values,
+ allowedAttributes->num_values,
+ sizeof(*allowedAttributes->values),
+ data_blob_cmp);
+
+ for (i=1 ; i < allowedAttributes->num_values; i++) {
+ struct ldb_val *val1 = &allowedAttributes->values[i-1];
+ struct ldb_val *val2 = &allowedAttributes->values[i];
+ if (data_blob_cmp(val1, val2) == 0) {
+ memmove(val1, val2, (allowedAttributes->num_values - i) * sizeof( struct ldb_val));
+ allowedAttributes->num_values--;
+ i--;
+ }
+ }
+ }
+
+ return 0;
+
+}
+
+/* find all attributes allowed by all these objectClasses */
+
static int kludge_acl_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
{
struct kludge_acl_context *ac;
struct kludge_private_data *data;
- int i;
+ int i, ret;
if (!context || !ares) {
- ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context or Result in callback"));
+ ldb_set_errstring(ldb, "NULL Context or Result in callback");
goto error;
}
ac = talloc_get_type(context, struct kludge_acl_context);
data = talloc_get_type(ac->module->private_data, struct kludge_private_data);
- if (ares->type == LDB_REPLY_ENTRY
- && data->password_attrs) /* if we are not initialized just get through */
+ if (ares->type != LDB_REPLY_ENTRY) {
+ return ac->up_callback(ldb, ac->up_context, ares);
+ }
+
+ if (ac->allowedAttributes) {
+ ret = kludge_acl_allowedAttributes(ldb, ares->message, "allowedAttributes");
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ if (data && data->password_attrs) /* if we are not initialized just get through */
{
switch (ac->user_type) {
case SYSTEM:
case ADMINISTRATOR:
+ if (ac->allowedAttributesEffective) {
+ ret = kludge_acl_allowedAttributes(ldb, ares->message, "allowedAttributesEffective");
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
break;
default:
/* remove password attributes */
}
}
+ if ((ac->allowedAttributes || ac->allowedAttributesEffective) &&
+ (!ldb_attr_in_list(ac->attrs, "objectClass") &&
+ !ldb_attr_in_list(ac->attrs, "*"))) {
+ ldb_msg_remove_attr(ares->message, "objectClass");
+ }
+
return ac->up_callback(ldb, ac->up_context, ares);
error:
{
struct kludge_acl_context *ac;
struct ldb_request *down_req;
- int ret;
+ struct kludge_private_data *data;
+ int ret, i;
req->handle = NULL;
return LDB_ERR_OPERATIONS_ERROR;
}
+ data = talloc_get_type(module->private_data, struct kludge_private_data);
+
ac->module = module;
ac->up_context = req->context;
ac->up_callback = req->callback;
ac->user_type = what_is_user(module);
+ ac->attrs = req->op.search.attrs;
down_req = talloc_zero(req, struct ldb_request);
if (down_req == NULL) {
down_req->op.search.scope = req->op.search.scope;
down_req->op.search.tree = req->op.search.tree;
down_req->op.search.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");
+
+ if (ac->allowedAttributes || ac->allowedAttributesEffective) {
+ down_req->op.search.attrs
+ = ldb_attr_list_copy_add(down_req, down_req->op.search.attrs, "objectClass");
+ }
+
+ /* FIXME: I hink we should copy the tree and keep the original
+ * unmodified. SSS */
+ /* replace any attributes in the parse tree that are private,
+ so we don't allow a search for 'sambaPassword=penguin',
+ just as we would not allow that attribute to be returned */
+ switch (ac->user_type) {
+ case SYSTEM:
+ break;
+ default:
+ /* remove password attributes */
+ for (i = 0; data && data->password_attrs && data->password_attrs[i]; i++) {
+ ldb_parse_tree_attr_replace(down_req->op.search.tree,
+ data->password_attrs[i],
+ "kludgeACLredactedattribute");
+ }
+ }
+
down_req->controls = req->controls;
down_req->context = ac;
case ADMINISTRATOR:
return ldb_next_request(module, req);
default:
- ldb_set_errstring(module->ldb,
- talloc_asprintf(req, "kludge_acl_change: "
- "attempted database modify not permitted. User %s is not SYSTEM or an administrator",
- user_name(req, module)));
+ ldb_asprintf_errstring(module->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;
}
}
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = ldb_search(module->ldb, ldb_dn_explode(mem_ctx, "@KLUDGEACL"),
+ ret = ldb_search(module->ldb, ldb_dn_new(mem_ctx, module->ldb, "@KLUDGEACL"),
LDB_SCOPE_BASE,
NULL, attrs,
&res);
.modify = kludge_acl_change,
.del = kludge_acl_change,
.rename = kludge_acl_change,
+ .extended = kludge_acl_change,
.init_context = kludge_acl_init
};