4 Copyright (C) Stefan Metzmacher <metze@samba.org> 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "ldb_module.h"
22 #include "dsdb/samdb/samdb.h"
24 static int resolve_oids_need_value(struct ldb_context *ldb,
25 struct dsdb_schema *schema,
26 const struct dsdb_attribute *a,
27 const struct ldb_val *valp)
29 const struct dsdb_attribute *va = NULL;
30 const struct dsdb_class *vo = NULL;
34 if (a->syntax->oMSyntax != 6) {
35 return LDB_ERR_COMPARE_FALSE;
39 p2 = memchr(valp->data, '.', valp->length);
45 return LDB_ERR_COMPARE_FALSE;
48 switch (a->attributeID_id) {
49 case DRSUAPI_ATTRIBUTE_objectClass:
50 case DRSUAPI_ATTRIBUTE_subClassOf:
51 case DRSUAPI_ATTRIBUTE_auxiliaryClass:
52 case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
53 case DRSUAPI_ATTRIBUTE_possSuperiors:
54 str = talloc_strndup(ldb, (char *)valp->data, valp->length);
58 vo = dsdb_class_by_governsID_oid(schema, str);
61 return LDB_ERR_COMPARE_FALSE;
63 return LDB_ERR_COMPARE_TRUE;
64 case DRSUAPI_ATTRIBUTE_systemMustContain:
65 case DRSUAPI_ATTRIBUTE_systemMayContain:
66 case DRSUAPI_ATTRIBUTE_mustContain:
67 case DRSUAPI_ATTRIBUTE_mayContain:
68 str = talloc_strndup(ldb, (char *)valp->data, valp->length);
72 va = dsdb_attribute_by_attributeID_oid(schema, str);
75 return LDB_ERR_COMPARE_FALSE;
77 return LDB_ERR_COMPARE_TRUE;
78 case DRSUAPI_ATTRIBUTE_governsID:
79 case DRSUAPI_ATTRIBUTE_attributeID:
80 case DRSUAPI_ATTRIBUTE_attributeSyntax:
81 return LDB_ERR_COMPARE_FALSE;
84 return LDB_ERR_COMPARE_FALSE;
87 static int resolve_oids_parse_tree_need(struct ldb_context *ldb,
88 struct dsdb_schema *schema,
89 const struct ldb_parse_tree *tree)
92 const struct dsdb_attribute *a = NULL;
96 const struct ldb_val *valp = NULL;
99 switch (tree->operation) {
102 for (i=0;i<tree->u.list.num_elements;i++) {
103 ret = resolve_oids_parse_tree_need(ldb, schema,
104 tree->u.list.elements[i]);
105 if (ret != LDB_ERR_COMPARE_FALSE) {
109 return LDB_ERR_COMPARE_FALSE;
111 return resolve_oids_parse_tree_need(ldb, schema,
112 tree->u.isnot.child);
113 case LDB_OP_EQUALITY:
117 attr = tree->u.equality.attr;
118 valp = &tree->u.equality.value;
120 case LDB_OP_SUBSTRING:
121 attr = tree->u.substring.attr;
124 attr = tree->u.present.attr;
126 case LDB_OP_EXTENDED:
127 attr = tree->u.extended.attr;
128 valp = &tree->u.extended.value;
131 return LDB_ERR_COMPARE_FALSE;
134 p1 = strchr(attr, '.');
137 p2 = memchr(valp->data, '.', valp->length);
143 return LDB_ERR_COMPARE_FALSE;
147 a = dsdb_attribute_by_attributeID_oid(schema, attr);
149 a = dsdb_attribute_by_lDAPDisplayName(schema, attr);
152 return LDB_ERR_COMPARE_FALSE;
156 return LDB_ERR_COMPARE_FALSE;
159 return resolve_oids_need_value(ldb, schema, a, valp);
162 static int resolve_oids_element_need(struct ldb_context *ldb,
163 struct dsdb_schema *schema,
164 const struct ldb_message_element *el)
167 const struct dsdb_attribute *a = NULL;
170 p1 = strchr(el->name, '.');
173 a = dsdb_attribute_by_attributeID_oid(schema, el->name);
175 a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
178 return LDB_ERR_COMPARE_FALSE;
181 for (i=0; i < el->num_values; i++) {
183 ret = resolve_oids_need_value(ldb, schema, a,
185 if (ret != LDB_ERR_COMPARE_FALSE) {
190 return LDB_ERR_COMPARE_FALSE;
193 static int resolve_oids_message_need(struct ldb_context *ldb,
194 struct dsdb_schema *schema,
195 const struct ldb_message *msg)
199 for (i=0; i < msg->num_elements; i++) {
201 ret = resolve_oids_element_need(ldb, schema,
203 if (ret != LDB_ERR_COMPARE_FALSE) {
208 return LDB_ERR_COMPARE_FALSE;
211 static int resolve_oids_replace_value(struct ldb_context *ldb,
212 struct dsdb_schema *schema,
213 const struct dsdb_attribute *a,
214 struct ldb_val *valp)
216 const struct dsdb_attribute *va = NULL;
217 const struct dsdb_class *vo = NULL;
221 if (a->syntax->oMSyntax != 6) {
226 p2 = memchr(valp->data, '.', valp->length);
235 switch (a->attributeID_id) {
236 case DRSUAPI_ATTRIBUTE_objectClass:
237 case DRSUAPI_ATTRIBUTE_subClassOf:
238 case DRSUAPI_ATTRIBUTE_auxiliaryClass:
239 case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
240 case DRSUAPI_ATTRIBUTE_possSuperiors:
241 str = talloc_strndup(schema, (char *)valp->data, valp->length);
245 vo = dsdb_class_by_governsID_oid(schema, str);
250 *valp = data_blob_string_const(vo->lDAPDisplayName);
252 case DRSUAPI_ATTRIBUTE_systemMustContain:
253 case DRSUAPI_ATTRIBUTE_systemMayContain:
254 case DRSUAPI_ATTRIBUTE_mustContain:
255 case DRSUAPI_ATTRIBUTE_mayContain:
256 str = talloc_strndup(schema, (char *)valp->data, valp->length);
260 va = dsdb_attribute_by_attributeID_oid(schema, str);
265 *valp = data_blob_string_const(va->lDAPDisplayName);
267 case DRSUAPI_ATTRIBUTE_governsID:
268 case DRSUAPI_ATTRIBUTE_attributeID:
269 case DRSUAPI_ATTRIBUTE_attributeSyntax:
276 static int resolve_oids_parse_tree_replace(struct ldb_context *ldb,
277 struct dsdb_schema *schema,
278 struct ldb_parse_tree *tree)
281 const struct dsdb_attribute *a = NULL;
285 struct ldb_val *valp = NULL;
288 switch (tree->operation) {
291 for (i=0;i<tree->u.list.num_elements;i++) {
292 ret = resolve_oids_parse_tree_replace(ldb, schema,
293 tree->u.list.elements[i]);
294 if (ret != LDB_SUCCESS) {
300 return resolve_oids_parse_tree_replace(ldb, schema,
301 tree->u.isnot.child);
302 case LDB_OP_EQUALITY:
306 attrp = &tree->u.equality.attr;
307 valp = &tree->u.equality.value;
309 case LDB_OP_SUBSTRING:
310 attrp = &tree->u.substring.attr;
313 attrp = &tree->u.present.attr;
315 case LDB_OP_EXTENDED:
316 attrp = &tree->u.extended.attr;
317 valp = &tree->u.extended.value;
323 p1 = strchr(*attrp, '.');
326 p2 = memchr(valp->data, '.', valp->length);
336 a = dsdb_attribute_by_attributeID_oid(schema, *attrp);
338 a = dsdb_attribute_by_lDAPDisplayName(schema, *attrp);
344 *attrp = a->lDAPDisplayName;
350 if (a->syntax->oMSyntax != 6) {
354 return resolve_oids_replace_value(ldb, schema, a, valp);
357 static int resolve_oids_element_replace(struct ldb_context *ldb,
358 struct dsdb_schema *schema,
359 struct ldb_message_element *el)
362 const struct dsdb_attribute *a = NULL;
365 p1 = strchr(el->name, '.');
368 a = dsdb_attribute_by_attributeID_oid(schema, el->name);
370 a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
376 el->name = a->lDAPDisplayName;
378 for (i=0; i < el->num_values; i++) {
380 ret = resolve_oids_replace_value(ldb, schema, a,
382 if (ret != LDB_SUCCESS) {
390 static int resolve_oids_message_replace(struct ldb_context *ldb,
391 struct dsdb_schema *schema,
392 struct ldb_message *msg)
396 for (i=0; i < msg->num_elements; i++) {
398 ret = resolve_oids_element_replace(ldb, schema,
400 if (ret != LDB_SUCCESS) {
408 struct resolve_oids_context {
409 struct ldb_module *module;
410 struct ldb_request *req;
413 static int resolve_oids_callback(struct ldb_request *req, struct ldb_reply *ares)
415 struct ldb_context *ldb;
416 struct resolve_oids_context *ac;
418 ac = talloc_get_type_abort(req->context, struct resolve_oids_context);
419 ldb = ldb_module_get_ctx(ac->module);
422 return ldb_module_done(ac->req, NULL, NULL,
423 LDB_ERR_OPERATIONS_ERROR);
425 if (ares->error != LDB_SUCCESS) {
426 return ldb_module_done(ac->req, ares->controls,
427 ares->response, ares->error);
430 switch (ares->type) {
431 case LDB_REPLY_ENTRY:
432 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
434 case LDB_REPLY_REFERRAL:
435 return ldb_module_send_referral(ac->req, ares->referral);
438 return ldb_module_done(ac->req, ares->controls,
439 ares->response, LDB_SUCCESS);
445 static int resolve_oids_search(struct ldb_module *module, struct ldb_request *req)
447 struct ldb_context *ldb;
448 struct dsdb_schema *schema;
449 struct ldb_parse_tree *tree;
450 struct ldb_request *down_req;
451 struct resolve_oids_context *ac;
454 const char * const *attrs1;
458 ldb = ldb_module_get_ctx(module);
459 schema = dsdb_get_schema(ldb, NULL);
462 return ldb_next_request(module, req);
465 /* do not manipulate our control entries */
466 if (ldb_dn_is_special(req->op.search.base)) {
467 return ldb_next_request(module, req);
470 ret = resolve_oids_parse_tree_need(ldb, schema,
471 req->op.search.tree);
472 if (ret == LDB_ERR_COMPARE_TRUE) {
474 } else if (ret != LDB_ERR_COMPARE_FALSE) {
478 attrs1 = req->op.search.attrs;
480 for (i=0; attrs1 && attrs1[i]; i++) {
482 const struct dsdb_attribute *a;
484 p = strchr(attrs1[i], '.');
489 a = dsdb_attribute_by_attributeID_oid(schema, attrs1[i]);
499 return ldb_next_request(module, req);
502 ac = talloc(req, struct resolve_oids_context);
509 tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree);
514 schema = talloc_reference(tree, schema);
519 ret = resolve_oids_parse_tree_replace(ldb, schema,
521 if (ret != LDB_SUCCESS) {
525 attrs2 = str_list_copy_const(ac,
526 discard_const_p(const char *, req->op.search.attrs));
527 if (req->op.search.attrs && !attrs2) {
531 for (i=0; attrs2 && attrs2[i]; i++) {
533 const struct dsdb_attribute *a;
535 p = strchr(attrs2[i], '.');
540 a = dsdb_attribute_by_attributeID_oid(schema, attrs2[i]);
545 attrs2[i] = a->lDAPDisplayName;
548 ret = ldb_build_search_req_ex(&down_req, ldb, ac,
550 req->op.search.scope,
554 ac, resolve_oids_callback,
556 LDB_REQ_SET_LOCATION(down_req);
557 if (ret != LDB_SUCCESS) {
561 /* go on with the call chain */
562 return ldb_next_request(module, down_req);
565 static int resolve_oids_add(struct ldb_module *module, struct ldb_request *req)
567 struct ldb_context *ldb;
568 struct dsdb_schema *schema;
570 struct ldb_message *msg;
571 struct ldb_request *down_req;
572 struct resolve_oids_context *ac;
574 ldb = ldb_module_get_ctx(module);
575 schema = dsdb_get_schema(ldb, NULL);
578 return ldb_next_request(module, req);
581 /* do not manipulate our control entries */
582 if (ldb_dn_is_special(req->op.add.message->dn)) {
583 return ldb_next_request(module, req);
586 ret = resolve_oids_message_need(ldb, schema,
587 req->op.add.message);
588 if (ret == LDB_ERR_COMPARE_FALSE) {
589 return ldb_next_request(module, req);
590 } else if (ret != LDB_ERR_COMPARE_TRUE) {
594 ac = talloc(req, struct resolve_oids_context);
601 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
606 if (!talloc_reference(msg, schema)) {
610 ret = resolve_oids_message_replace(ldb, schema, msg);
611 if (ret != LDB_SUCCESS) {
615 ret = ldb_build_add_req(&down_req, ldb, ac,
618 ac, resolve_oids_callback,
620 LDB_REQ_SET_LOCATION(down_req);
621 if (ret != LDB_SUCCESS) {
625 /* go on with the call chain */
626 return ldb_next_request(module, down_req);
629 static int resolve_oids_modify(struct ldb_module *module, struct ldb_request *req)
631 struct ldb_context *ldb;
632 struct dsdb_schema *schema;
634 struct ldb_message *msg;
635 struct ldb_request *down_req;
636 struct resolve_oids_context *ac;
638 ldb = ldb_module_get_ctx(module);
639 schema = dsdb_get_schema(ldb, NULL);
642 return ldb_next_request(module, req);
645 /* do not manipulate our control entries */
646 if (ldb_dn_is_special(req->op.mod.message->dn)) {
647 return ldb_next_request(module, req);
650 ret = resolve_oids_message_need(ldb, schema,
651 req->op.mod.message);
652 if (ret == LDB_ERR_COMPARE_FALSE) {
653 return ldb_next_request(module, req);
654 } else if (ret != LDB_ERR_COMPARE_TRUE) {
658 ac = talloc(req, struct resolve_oids_context);
665 /* we have to copy the message as the caller might have it as a const */
666 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
671 if (!talloc_reference(msg, schema)) {
675 ret = resolve_oids_message_replace(ldb, schema, msg);
676 if (ret != LDB_SUCCESS) {
680 ret = ldb_build_mod_req(&down_req, ldb, ac,
683 ac, resolve_oids_callback,
685 LDB_REQ_SET_LOCATION(down_req);
686 if (ret != LDB_SUCCESS) {
690 /* go on with the call chain */
691 return ldb_next_request(module, down_req);
694 _PUBLIC_ const struct ldb_module_ops ldb_resolve_oids_module_ops = {
695 .name = "resolve_oids",
696 .search = resolve_oids_search,
697 .add = resolve_oids_add,
698 .modify = resolve_oids_modify,