summaryrefslogtreecommitdiffstats
path: root/source4/dsdb/samdb/ldb_modules/resolve_oids.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
commit8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch)
tree4099e8021376c7d8c05bdf8503093d80e9c7bad0 /source4/dsdb/samdb/ldb_modules/resolve_oids.c
parentInitial commit. (diff)
downloadsamba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz
samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules/resolve_oids.c')
-rw-r--r--source4/dsdb/samdb/ldb_modules/resolve_oids.c710
1 files changed, 710 insertions, 0 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/resolve_oids.c b/source4/dsdb/samdb/ldb_modules/resolve_oids.c
new file mode 100644
index 0000000..5c16396
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/resolve_oids.c
@@ -0,0 +1,710 @@
+/*
+ ldb database library
+
+ Copyright (C) Stefan Metzmacher <metze@samba.org> 2009
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "ldb_module.h"
+#include "dsdb/samdb/samdb.h"
+
+static int resolve_oids_need_value(struct ldb_context *ldb,
+ struct dsdb_schema *schema,
+ const struct dsdb_attribute *a,
+ const struct ldb_val *valp)
+{
+ const struct dsdb_attribute *va = NULL;
+ const struct dsdb_class *vo = NULL;
+ const void *p2;
+ char *str = NULL;
+
+ if (a->syntax->oMSyntax != 6) {
+ return LDB_ERR_COMPARE_FALSE;
+ }
+
+ if (valp) {
+ p2 = memchr(valp->data, '.', valp->length);
+ } else {
+ p2 = NULL;
+ }
+
+ if (!p2) {
+ return LDB_ERR_COMPARE_FALSE;
+ }
+
+ switch (a->attributeID_id) {
+ case DRSUAPI_ATTID_objectClass:
+ case DRSUAPI_ATTID_subClassOf:
+ case DRSUAPI_ATTID_auxiliaryClass:
+ case DRSUAPI_ATTID_systemPossSuperiors:
+ case DRSUAPI_ATTID_possSuperiors:
+ str = talloc_strndup(ldb, (char *)valp->data, valp->length);
+ if (!str) {
+ return ldb_oom(ldb);
+ }
+ vo = dsdb_class_by_governsID_oid(schema, str);
+ talloc_free(str);
+ if (!vo) {
+ return LDB_ERR_COMPARE_FALSE;
+ }
+ return LDB_ERR_COMPARE_TRUE;
+ case DRSUAPI_ATTID_systemMustContain:
+ case DRSUAPI_ATTID_systemMayContain:
+ case DRSUAPI_ATTID_mustContain:
+ case DRSUAPI_ATTID_mayContain:
+ str = talloc_strndup(ldb, (char *)valp->data, valp->length);
+ if (!str) {
+ return ldb_oom(ldb);
+ }
+ va = dsdb_attribute_by_attributeID_oid(schema, str);
+ talloc_free(str);
+ if (!va) {
+ return LDB_ERR_COMPARE_FALSE;
+ }
+ return LDB_ERR_COMPARE_TRUE;
+ case DRSUAPI_ATTID_governsID:
+ case DRSUAPI_ATTID_attributeID:
+ case DRSUAPI_ATTID_attributeSyntax:
+ return LDB_ERR_COMPARE_FALSE;
+ }
+
+ return LDB_ERR_COMPARE_FALSE;
+}
+
+static int resolve_oids_parse_tree_need(struct ldb_context *ldb,
+ struct dsdb_schema *schema,
+ const struct ldb_parse_tree *tree)
+{
+ unsigned int i;
+ const struct dsdb_attribute *a = NULL;
+ const char *attr;
+ const char *p1;
+ const void *p2;
+ const struct ldb_val *valp = NULL;
+ int ret;
+
+ switch (tree->operation) {
+ case LDB_OP_AND:
+ case LDB_OP_OR:
+ for (i=0;i<tree->u.list.num_elements;i++) {
+ ret = resolve_oids_parse_tree_need(ldb, schema,
+ tree->u.list.elements[i]);
+ if (ret != LDB_ERR_COMPARE_FALSE) {
+ return ret;
+ }
+ }
+ return LDB_ERR_COMPARE_FALSE;
+ case LDB_OP_NOT:
+ return resolve_oids_parse_tree_need(ldb, schema,
+ tree->u.isnot.child);
+ case LDB_OP_EQUALITY:
+ attr = tree->u.equality.attr;
+ valp = &tree->u.equality.value;
+ break;
+ case LDB_OP_GREATER:
+ case LDB_OP_LESS:
+ case LDB_OP_APPROX:
+ attr = tree->u.comparison.attr;
+ valp = &tree->u.comparison.value;
+ break;
+ case LDB_OP_SUBSTRING:
+ attr = tree->u.substring.attr;
+ break;
+ case LDB_OP_PRESENT:
+ attr = tree->u.present.attr;
+ break;
+ case LDB_OP_EXTENDED:
+ attr = tree->u.extended.attr;
+ valp = &tree->u.extended.value;
+ break;
+ default:
+ return LDB_ERR_COMPARE_FALSE;
+ }
+
+ p1 = strchr(attr, '.');
+
+ if (valp) {
+ p2 = memchr(valp->data, '.', valp->length);
+ } else {
+ p2 = NULL;
+ }
+
+ if (!p1 && !p2) {
+ return LDB_ERR_COMPARE_FALSE;
+ }
+
+ if (p1) {
+ a = dsdb_attribute_by_attributeID_oid(schema, attr);
+ } else {
+ a = dsdb_attribute_by_lDAPDisplayName(schema, attr);
+ }
+ if (!a) {
+ return LDB_ERR_COMPARE_FALSE;
+ }
+
+ if (!p2) {
+ return LDB_ERR_COMPARE_FALSE;
+ }
+
+ return resolve_oids_need_value(ldb, schema, a, valp);
+}
+
+static int resolve_oids_element_need(struct ldb_context *ldb,
+ struct dsdb_schema *schema,
+ const struct ldb_message_element *el)
+{
+ unsigned int i;
+ const struct dsdb_attribute *a = NULL;
+ const char *p1;
+
+ p1 = strchr(el->name, '.');
+
+ if (p1) {
+ a = dsdb_attribute_by_attributeID_oid(schema, el->name);
+ } else {
+ a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
+ }
+ if (!a) {
+ return LDB_ERR_COMPARE_FALSE;
+ }
+
+ for (i=0; i < el->num_values; i++) {
+ int ret;
+ ret = resolve_oids_need_value(ldb, schema, a,
+ &el->values[i]);
+ if (ret != LDB_ERR_COMPARE_FALSE) {
+ return ret;
+ }
+ }
+
+ return LDB_ERR_COMPARE_FALSE;
+}
+
+static int resolve_oids_message_need(struct ldb_context *ldb,
+ struct dsdb_schema *schema,
+ const struct ldb_message *msg)
+{
+ unsigned int i;
+
+ for (i=0; i < msg->num_elements; i++) {
+ int ret;
+ ret = resolve_oids_element_need(ldb, schema,
+ &msg->elements[i]);
+ if (ret != LDB_ERR_COMPARE_FALSE) {
+ return ret;
+ }
+ }
+
+ return LDB_ERR_COMPARE_FALSE;
+}
+
+static int resolve_oids_replace_value(struct ldb_context *ldb,
+ struct dsdb_schema *schema,
+ const struct dsdb_attribute *a,
+ struct ldb_val *valp)
+{
+ const struct dsdb_attribute *va = NULL;
+ const struct dsdb_class *vo = NULL;
+ const void *p2;
+ char *str = NULL;
+
+ if (a->syntax->oMSyntax != 6) {
+ return LDB_SUCCESS;
+ }
+
+ if (valp) {
+ p2 = memchr(valp->data, '.', valp->length);
+ } else {
+ p2 = NULL;
+ }
+
+ if (!p2) {
+ return LDB_SUCCESS;
+ }
+
+ switch (a->attributeID_id) {
+ case DRSUAPI_ATTID_objectClass:
+ case DRSUAPI_ATTID_subClassOf:
+ case DRSUAPI_ATTID_auxiliaryClass:
+ case DRSUAPI_ATTID_systemPossSuperiors:
+ case DRSUAPI_ATTID_possSuperiors:
+ str = talloc_strndup(schema, (char *)valp->data, valp->length);
+ if (!str) {
+ return ldb_oom(ldb);
+ }
+ vo = dsdb_class_by_governsID_oid(schema, str);
+ talloc_free(str);
+ if (!vo) {
+ return LDB_SUCCESS;
+ }
+ *valp = data_blob_string_const(vo->lDAPDisplayName);
+ return LDB_SUCCESS;
+ case DRSUAPI_ATTID_systemMustContain:
+ case DRSUAPI_ATTID_systemMayContain:
+ case DRSUAPI_ATTID_mustContain:
+ case DRSUAPI_ATTID_mayContain:
+ str = talloc_strndup(schema, (char *)valp->data, valp->length);
+ if (!str) {
+ return ldb_oom(ldb);
+ }
+ va = dsdb_attribute_by_attributeID_oid(schema, str);
+ talloc_free(str);
+ if (!va) {
+ return LDB_SUCCESS;
+ }
+ *valp = data_blob_string_const(va->lDAPDisplayName);
+ return LDB_SUCCESS;
+ case DRSUAPI_ATTID_governsID:
+ case DRSUAPI_ATTID_attributeID:
+ case DRSUAPI_ATTID_attributeSyntax:
+ return LDB_SUCCESS;
+ }
+
+ return LDB_SUCCESS;
+}
+
+static int resolve_oids_parse_tree_replace(struct ldb_context *ldb,
+ struct dsdb_schema *schema,
+ struct ldb_parse_tree *tree)
+{
+ unsigned int i;
+ const struct dsdb_attribute *a = NULL;
+ const char **attrp;
+ const char *p1;
+ const void *p2;
+ struct ldb_val *valp = NULL;
+ int ret;
+
+ switch (tree->operation) {
+ case LDB_OP_AND:
+ case LDB_OP_OR:
+ for (i=0;i<tree->u.list.num_elements;i++) {
+ ret = resolve_oids_parse_tree_replace(ldb, schema,
+ tree->u.list.elements[i]);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+ return LDB_SUCCESS;
+ case LDB_OP_NOT:
+ return resolve_oids_parse_tree_replace(ldb, schema,
+ tree->u.isnot.child);
+ case LDB_OP_EQUALITY:
+ attrp = &tree->u.equality.attr;
+ valp = &tree->u.equality.value;
+ break;
+ case LDB_OP_GREATER:
+ case LDB_OP_LESS:
+ case LDB_OP_APPROX:
+ attrp = &tree->u.comparison.attr;
+ valp = &tree->u.comparison.value;
+ break;
+ case LDB_OP_SUBSTRING:
+ attrp = &tree->u.substring.attr;
+ break;
+ case LDB_OP_PRESENT:
+ attrp = &tree->u.present.attr;
+ break;
+ case LDB_OP_EXTENDED:
+ attrp = &tree->u.extended.attr;
+ valp = &tree->u.extended.value;
+ break;
+ default:
+ return LDB_SUCCESS;
+ }
+
+ p1 = strchr(*attrp, '.');
+
+ if (valp) {
+ p2 = memchr(valp->data, '.', valp->length);
+ } else {
+ p2 = NULL;
+ }
+
+ if (!p1 && !p2) {
+ return LDB_SUCCESS;
+ }
+
+ if (p1) {
+ a = dsdb_attribute_by_attributeID_oid(schema, *attrp);
+ } else {
+ a = dsdb_attribute_by_lDAPDisplayName(schema, *attrp);
+ }
+ if (!a) {
+ return LDB_SUCCESS;
+ }
+
+ *attrp = a->lDAPDisplayName;
+
+ if (!p2) {
+ return LDB_SUCCESS;
+ }
+
+ if (a->syntax->oMSyntax != 6) {
+ return LDB_SUCCESS;
+ }
+
+ return resolve_oids_replace_value(ldb, schema, a, valp);
+}
+
+static int resolve_oids_element_replace(struct ldb_context *ldb,
+ struct dsdb_schema *schema,
+ struct ldb_message_element *el)
+{
+ unsigned int i;
+ const struct dsdb_attribute *a = NULL;
+ const char *p1;
+
+ p1 = strchr(el->name, '.');
+
+ if (p1) {
+ a = dsdb_attribute_by_attributeID_oid(schema, el->name);
+ } else {
+ a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
+ }
+ if (!a) {
+ return LDB_SUCCESS;
+ }
+
+ el->name = a->lDAPDisplayName;
+
+ for (i=0; i < el->num_values; i++) {
+ int ret;
+ ret = resolve_oids_replace_value(ldb, schema, a,
+ &el->values[i]);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ return LDB_SUCCESS;
+}
+
+static int resolve_oids_message_replace(struct ldb_context *ldb,
+ struct dsdb_schema *schema,
+ struct ldb_message *msg)
+{
+ unsigned int i;
+
+ for (i=0; i < msg->num_elements; i++) {
+ int ret;
+ ret = resolve_oids_element_replace(ldb, schema,
+ &msg->elements[i]);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ return LDB_SUCCESS;
+}
+
+struct resolve_oids_context {
+ struct ldb_module *module;
+ struct ldb_request *req;
+};
+
+static int resolve_oids_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+ struct resolve_oids_context *ac;
+
+ ac = talloc_get_type_abort(req->context, struct resolve_oids_context);
+
+ 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:
+ 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 resolve_oids_search(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_context *ldb;
+ struct dsdb_schema *schema;
+ struct ldb_parse_tree *tree;
+ struct ldb_request *down_req;
+ struct resolve_oids_context *ac;
+ int ret;
+ bool needed = false;
+ const char * const *attrs1;
+ const char **attrs2;
+ unsigned int i;
+
+ ldb = ldb_module_get_ctx(module);
+ schema = dsdb_get_schema(ldb, NULL);
+
+ if (!schema) {
+ return ldb_next_request(module, req);
+ }
+
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.search.base)) {
+ return ldb_next_request(module, req);
+ }
+
+ ret = resolve_oids_parse_tree_need(ldb, schema,
+ req->op.search.tree);
+ if (ret == LDB_ERR_COMPARE_TRUE) {
+ needed = true;
+ } else if (ret != LDB_ERR_COMPARE_FALSE) {
+ return ret;
+ }
+
+ attrs1 = req->op.search.attrs;
+
+ for (i=0; attrs1 && attrs1[i]; i++) {
+ const char *p;
+ const struct dsdb_attribute *a;
+
+ p = strchr(attrs1[i], '.');
+ if (p == NULL) {
+ continue;
+ }
+
+ a = dsdb_attribute_by_attributeID_oid(schema, attrs1[i]);
+ if (a == NULL) {
+ continue;
+ }
+
+ needed = true;
+ break;
+ }
+
+ if (!needed) {
+ return ldb_next_request(module, req);
+ }
+
+ ac = talloc(req, struct resolve_oids_context);
+ if (ac == NULL) {
+ return ldb_oom(ldb);
+ }
+ ac->module = module;
+ ac->req = req;
+
+ tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree);
+ if (!tree) {
+ return ldb_oom(ldb);
+ }
+
+ schema = talloc_reference(tree, schema);
+ if (!schema) {
+ return ldb_oom(ldb);
+ }
+
+ ret = resolve_oids_parse_tree_replace(ldb, schema,
+ tree);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ attrs2 = str_list_copy_const(ac,
+ discard_const_p(const char *, req->op.search.attrs));
+ if (req->op.search.attrs && !attrs2) {
+ return ldb_oom(ldb);
+ }
+
+ for (i=0; attrs2 && attrs2[i]; i++) {
+ const char *p;
+ const struct dsdb_attribute *a;
+
+ p = strchr(attrs2[i], '.');
+ if (p == NULL) {
+ continue;
+ }
+
+ a = dsdb_attribute_by_attributeID_oid(schema, attrs2[i]);
+ if (a == NULL) {
+ continue;
+ }
+
+ attrs2[i] = a->lDAPDisplayName;
+ }
+
+ ret = ldb_build_search_req_ex(&down_req, ldb, ac,
+ req->op.search.base,
+ req->op.search.scope,
+ tree,
+ attrs2,
+ req->controls,
+ ac, resolve_oids_callback,
+ req);
+ LDB_REQ_SET_LOCATION(down_req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ /* go on with the call chain */
+ return ldb_next_request(module, down_req);
+}
+
+static int resolve_oids_add(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_context *ldb;
+ struct dsdb_schema *schema;
+ int ret;
+ struct ldb_message *msg;
+ struct ldb_request *down_req;
+ struct resolve_oids_context *ac;
+
+ ldb = ldb_module_get_ctx(module);
+ schema = dsdb_get_schema(ldb, NULL);
+
+ if (!schema) {
+ return ldb_next_request(module, req);
+ }
+
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.add.message->dn)) {
+ return ldb_next_request(module, req);
+ }
+
+ ret = resolve_oids_message_need(ldb, schema,
+ req->op.add.message);
+ if (ret == LDB_ERR_COMPARE_FALSE) {
+ return ldb_next_request(module, req);
+ } else if (ret != LDB_ERR_COMPARE_TRUE) {
+ return ret;
+ }
+
+ ac = talloc(req, struct resolve_oids_context);
+ if (ac == NULL) {
+ return ldb_oom(ldb);
+ }
+ ac->module = module;
+ ac->req = req;
+
+ msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
+ if (!msg) {
+ return ldb_oom(ldb);
+ }
+
+ if (!talloc_reference(msg, schema)) {
+ return ldb_oom(ldb);
+ }
+
+ ret = resolve_oids_message_replace(ldb, schema, msg);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ret = ldb_build_add_req(&down_req, ldb, ac,
+ msg,
+ req->controls,
+ ac, resolve_oids_callback,
+ req);
+ LDB_REQ_SET_LOCATION(down_req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ /* go on with the call chain */
+ return ldb_next_request(module, down_req);
+}
+
+static int resolve_oids_modify(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_context *ldb;
+ struct dsdb_schema *schema;
+ int ret;
+ struct ldb_message *msg;
+ struct ldb_request *down_req;
+ struct resolve_oids_context *ac;
+
+ ldb = ldb_module_get_ctx(module);
+ schema = dsdb_get_schema(ldb, NULL);
+
+ if (!schema) {
+ return ldb_next_request(module, req);
+ }
+
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.mod.message->dn)) {
+ return ldb_next_request(module, req);
+ }
+
+ ret = resolve_oids_message_need(ldb, schema,
+ req->op.mod.message);
+ if (ret == LDB_ERR_COMPARE_FALSE) {
+ return ldb_next_request(module, req);
+ } else if (ret != LDB_ERR_COMPARE_TRUE) {
+ return ret;
+ }
+
+ ac = talloc(req, struct resolve_oids_context);
+ if (ac == NULL) {
+ return ldb_oom(ldb);
+ }
+ ac->module = module;
+ ac->req = req;
+
+ /* we have to copy the message as the caller might have it as a const */
+ msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
+ if (msg == NULL) {
+ return ldb_oom(ldb);
+ }
+
+ if (!talloc_reference(msg, schema)) {
+ return ldb_oom(ldb);
+ }
+
+ ret = resolve_oids_message_replace(ldb, schema, msg);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ret = ldb_build_mod_req(&down_req, ldb, ac,
+ msg,
+ req->controls,
+ ac, resolve_oids_callback,
+ req);
+ LDB_REQ_SET_LOCATION(down_req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ /* go on with the call chain */
+ return ldb_next_request(module, down_req);
+}
+
+static const struct ldb_module_ops ldb_resolve_oids_module_ops = {
+ .name = "resolve_oids",
+ .search = resolve_oids_search,
+ .add = resolve_oids_add,
+ .modify = resolve_oids_modify,
+};
+
+
+int ldb_resolve_oids_module_init(const char *version)
+{
+ LDB_MODULE_CHECK_VERSION(version);
+ return ldb_register_module(&ldb_resolve_oids_module_ops);
+}