s4:resolve_oids LDB module - not really a change but a nicer method to call "talloc_r...
[Samba/nascimento.git] / source4 / dsdb / samdb / ldb_modules / resolve_oids.c
blob16cabc18cdbf026800625cbdaa1e8212f5b31d7e
1 /*
2 ldb database library
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/>.
20 #include "includes.h"
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;
31 const void *p2;
32 char *str = NULL;
34 if (a->syntax->oMSyntax != 6) {
35 return LDB_ERR_COMPARE_FALSE;
38 if (valp) {
39 p2 = memchr(valp->data, '.', valp->length);
40 } else {
41 p2 = NULL;
44 if (!p2) {
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);
55 if (!str) {
56 ldb_oom(ldb);
57 return LDB_ERR_OPERATIONS_ERROR;
59 vo = dsdb_class_by_governsID_oid(schema, str);
60 talloc_free(str);
61 if (!vo) {
62 return LDB_ERR_COMPARE_FALSE;
64 return LDB_ERR_COMPARE_TRUE;
65 case DRSUAPI_ATTRIBUTE_systemMustContain:
66 case DRSUAPI_ATTRIBUTE_systemMayContain:
67 case DRSUAPI_ATTRIBUTE_mustContain:
68 case DRSUAPI_ATTRIBUTE_mayContain:
69 str = talloc_strndup(ldb, (char *)valp->data, valp->length);
70 if (!str) {
71 ldb_oom(ldb);
72 return LDB_ERR_OPERATIONS_ERROR;
74 va = dsdb_attribute_by_attributeID_oid(schema, str);
75 talloc_free(str);
76 if (!va) {
77 return LDB_ERR_COMPARE_FALSE;
79 return LDB_ERR_COMPARE_TRUE;
80 case DRSUAPI_ATTRIBUTE_governsID:
81 case DRSUAPI_ATTRIBUTE_attributeID:
82 case DRSUAPI_ATTRIBUTE_attributeSyntax:
83 return LDB_ERR_COMPARE_FALSE;
86 return LDB_ERR_COMPARE_FALSE;
89 static int resolve_oids_parse_tree_need(struct ldb_context *ldb,
90 struct dsdb_schema *schema,
91 const struct ldb_parse_tree *tree)
93 unsigned int i;
94 const struct dsdb_attribute *a = NULL;
95 const char *attr;
96 const char *p1;
97 const void *p2;
98 const struct ldb_val *valp = NULL;
99 int ret;
101 switch (tree->operation) {
102 case LDB_OP_AND:
103 case LDB_OP_OR:
104 for (i=0;i<tree->u.list.num_elements;i++) {
105 ret = resolve_oids_parse_tree_need(ldb, schema,
106 tree->u.list.elements[i]);
107 if (ret != LDB_ERR_COMPARE_FALSE) {
108 return ret;
111 return LDB_ERR_COMPARE_FALSE;
112 case LDB_OP_NOT:
113 return resolve_oids_parse_tree_need(ldb, schema,
114 tree->u.isnot.child);
115 case LDB_OP_EQUALITY:
116 case LDB_OP_GREATER:
117 case LDB_OP_LESS:
118 case LDB_OP_APPROX:
119 attr = tree->u.equality.attr;
120 valp = &tree->u.equality.value;
121 break;
122 case LDB_OP_SUBSTRING:
123 attr = tree->u.substring.attr;
124 break;
125 case LDB_OP_PRESENT:
126 attr = tree->u.present.attr;
127 break;
128 case LDB_OP_EXTENDED:
129 attr = tree->u.extended.attr;
130 valp = &tree->u.extended.value;
131 break;
132 default:
133 return LDB_ERR_COMPARE_FALSE;
136 p1 = strchr(attr, '.');
138 if (valp) {
139 p2 = memchr(valp->data, '.', valp->length);
140 } else {
141 p2 = NULL;
144 if (!p1 && !p2) {
145 return LDB_ERR_COMPARE_FALSE;
148 if (p1) {
149 a = dsdb_attribute_by_attributeID_oid(schema, attr);
150 } else {
151 a = dsdb_attribute_by_lDAPDisplayName(schema, attr);
153 if (!a) {
154 return LDB_ERR_COMPARE_FALSE;
157 if (!p2) {
158 return LDB_ERR_COMPARE_FALSE;
161 if (a->syntax->oMSyntax != 6) {
162 return LDB_ERR_COMPARE_FALSE;
165 return resolve_oids_need_value(ldb, schema, a, valp);
168 static int resolve_oids_element_need(struct ldb_context *ldb,
169 struct dsdb_schema *schema,
170 const struct ldb_message_element *el)
172 unsigned int i;
173 const struct dsdb_attribute *a = NULL;
174 const char *p1;
176 p1 = strchr(el->name, '.');
178 if (p1) {
179 a = dsdb_attribute_by_attributeID_oid(schema, el->name);
180 } else {
181 a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
183 if (!a) {
184 return LDB_ERR_COMPARE_FALSE;
187 for (i=0; i < el->num_values; i++) {
188 int ret;
189 ret = resolve_oids_need_value(ldb, schema, a,
190 &el->values[i]);
191 if (ret != LDB_ERR_COMPARE_FALSE) {
192 return ret;
196 return LDB_ERR_COMPARE_FALSE;
199 static int resolve_oids_message_need(struct ldb_context *ldb,
200 struct dsdb_schema *schema,
201 const struct ldb_message *msg)
203 int i;
205 for (i=0; i < msg->num_elements; i++) {
206 int ret;
207 ret = resolve_oids_element_need(ldb, schema,
208 &msg->elements[i]);
209 if (ret != LDB_ERR_COMPARE_FALSE) {
210 return ret;
214 return LDB_ERR_COMPARE_FALSE;
217 static int resolve_oids_replace_value(struct ldb_context *ldb,
218 struct dsdb_schema *schema,
219 const struct dsdb_attribute *a,
220 struct ldb_val *valp)
222 const struct dsdb_attribute *va = NULL;
223 const struct dsdb_class *vo = NULL;
224 const void *p2;
225 char *str = NULL;
227 if (a->syntax->oMSyntax != 6) {
228 return LDB_SUCCESS;
231 if (valp) {
232 p2 = memchr(valp->data, '.', valp->length);
233 } else {
234 p2 = NULL;
237 if (!p2) {
238 return LDB_SUCCESS;
241 switch (a->attributeID_id) {
242 case DRSUAPI_ATTRIBUTE_objectClass:
243 case DRSUAPI_ATTRIBUTE_subClassOf:
244 case DRSUAPI_ATTRIBUTE_auxiliaryClass:
245 case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
246 case DRSUAPI_ATTRIBUTE_possSuperiors:
247 str = talloc_strndup(schema, (char *)valp->data, valp->length);
248 if (!str) {
249 ldb_oom(ldb);
250 return LDB_ERR_OPERATIONS_ERROR;
252 vo = dsdb_class_by_governsID_oid(schema, str);
253 talloc_free(str);
254 if (!vo) {
255 return LDB_SUCCESS;
257 *valp = data_blob_string_const(vo->lDAPDisplayName);
258 return LDB_SUCCESS;
259 case DRSUAPI_ATTRIBUTE_systemMustContain:
260 case DRSUAPI_ATTRIBUTE_systemMayContain:
261 case DRSUAPI_ATTRIBUTE_mustContain:
262 case DRSUAPI_ATTRIBUTE_mayContain:
263 str = talloc_strndup(schema, (char *)valp->data, valp->length);
264 if (!str) {
265 ldb_oom(ldb);
266 return LDB_ERR_OPERATIONS_ERROR;
268 va = dsdb_attribute_by_attributeID_oid(schema, str);
269 talloc_free(str);
270 if (!va) {
271 return LDB_SUCCESS;
273 *valp = data_blob_string_const(va->lDAPDisplayName);
274 return LDB_SUCCESS;
275 case DRSUAPI_ATTRIBUTE_governsID:
276 case DRSUAPI_ATTRIBUTE_attributeID:
277 case DRSUAPI_ATTRIBUTE_attributeSyntax:
278 return LDB_SUCCESS;
281 return LDB_SUCCESS;
284 static int resolve_oids_parse_tree_replace(struct ldb_context *ldb,
285 struct dsdb_schema *schema,
286 struct ldb_parse_tree *tree)
288 unsigned int i;
289 const struct dsdb_attribute *a = NULL;
290 const char **attrp;
291 const char *p1;
292 const void *p2;
293 struct ldb_val *valp = NULL;
294 int ret;
296 switch (tree->operation) {
297 case LDB_OP_AND:
298 case LDB_OP_OR:
299 for (i=0;i<tree->u.list.num_elements;i++) {
300 ret = resolve_oids_parse_tree_replace(ldb, schema,
301 tree->u.list.elements[i]);
302 if (ret != LDB_SUCCESS) {
303 return ret;
306 return LDB_SUCCESS;
307 case LDB_OP_NOT:
308 return resolve_oids_parse_tree_replace(ldb, schema,
309 tree->u.isnot.child);
310 case LDB_OP_EQUALITY:
311 case LDB_OP_GREATER:
312 case LDB_OP_LESS:
313 case LDB_OP_APPROX:
314 attrp = &tree->u.equality.attr;
315 valp = &tree->u.equality.value;
316 break;
317 case LDB_OP_SUBSTRING:
318 attrp = &tree->u.substring.attr;
319 break;
320 case LDB_OP_PRESENT:
321 attrp = &tree->u.present.attr;
322 break;
323 case LDB_OP_EXTENDED:
324 attrp = &tree->u.extended.attr;
325 valp = &tree->u.extended.value;
326 break;
327 default:
328 return LDB_SUCCESS;
331 p1 = strchr(*attrp, '.');
333 if (valp) {
334 p2 = memchr(valp->data, '.', valp->length);
335 } else {
336 p2 = NULL;
339 if (!p1 && !p2) {
340 return LDB_SUCCESS;
343 if (p1) {
344 a = dsdb_attribute_by_attributeID_oid(schema, *attrp);
345 } else {
346 a = dsdb_attribute_by_lDAPDisplayName(schema, *attrp);
348 if (!a) {
349 return LDB_SUCCESS;
352 *attrp = a->lDAPDisplayName;
354 if (!p2) {
355 return LDB_SUCCESS;
358 if (a->syntax->oMSyntax != 6) {
359 return LDB_SUCCESS;
362 return resolve_oids_replace_value(ldb, schema, a, valp);
365 static int resolve_oids_element_replace(struct ldb_context *ldb,
366 struct dsdb_schema *schema,
367 struct ldb_message_element *el)
369 unsigned int i;
370 const struct dsdb_attribute *a = NULL;
371 const char *p1;
373 p1 = strchr(el->name, '.');
375 if (p1) {
376 a = dsdb_attribute_by_attributeID_oid(schema, el->name);
377 } else {
378 a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
380 if (!a) {
381 return LDB_SUCCESS;
384 el->name = a->lDAPDisplayName;
386 for (i=0; i < el->num_values; i++) {
387 int ret;
388 ret = resolve_oids_replace_value(ldb, schema, a,
389 &el->values[i]);
390 if (ret != LDB_SUCCESS) {
391 return ret;
395 return LDB_SUCCESS;
398 static int resolve_oids_message_replace(struct ldb_context *ldb,
399 struct dsdb_schema *schema,
400 struct ldb_message *msg)
402 unsigned int i;
404 for (i=0; i < msg->num_elements; i++) {
405 int ret;
406 ret = resolve_oids_element_replace(ldb, schema,
407 &msg->elements[i]);
408 if (ret != LDB_SUCCESS) {
409 return ret;
413 return LDB_SUCCESS;
416 struct resolve_oids_context {
417 struct ldb_module *module;
418 struct ldb_request *req;
421 static int resolve_oids_callback(struct ldb_request *req, struct ldb_reply *ares)
423 struct ldb_context *ldb;
424 struct resolve_oids_context *ac;
426 ac = talloc_get_type_abort(req->context, struct resolve_oids_context);
427 ldb = ldb_module_get_ctx(ac->module);
429 if (!ares) {
430 return ldb_module_done(ac->req, NULL, NULL,
431 LDB_ERR_OPERATIONS_ERROR);
433 if (ares->error != LDB_SUCCESS) {
434 return ldb_module_done(ac->req, ares->controls,
435 ares->response, ares->error);
438 switch (ares->type) {
439 case LDB_REPLY_ENTRY:
440 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
442 case LDB_REPLY_REFERRAL:
443 return ldb_module_send_referral(ac->req, ares->referral);
445 case LDB_REPLY_DONE:
446 return ldb_module_done(ac->req, ares->controls,
447 ares->response, LDB_SUCCESS);
450 return LDB_SUCCESS;
453 static int resolve_oids_search(struct ldb_module *module, struct ldb_request *req)
455 struct ldb_context *ldb;
456 struct dsdb_schema *schema;
457 struct ldb_parse_tree *tree;
458 struct ldb_request *down_req;
459 struct resolve_oids_context *ac;
460 int ret;
461 bool needed = false;
462 const char * const *attrs1;
463 const char **attrs2;
464 uint32_t i;
466 ldb = ldb_module_get_ctx(module);
467 schema = dsdb_get_schema(ldb, NULL);
469 if (!schema) {
470 return ldb_next_request(module, req);
473 /* do not manipulate our control entries */
474 if (ldb_dn_is_special(req->op.search.base)) {
475 return ldb_next_request(module, req);
478 ret = resolve_oids_parse_tree_need(ldb, schema,
479 req->op.search.tree);
480 if (ret == LDB_ERR_COMPARE_TRUE) {
481 needed = true;
482 } else if (ret != LDB_ERR_COMPARE_FALSE) {
483 return ret;
486 attrs1 = req->op.search.attrs;
488 for (i=0; attrs1 && attrs1[i]; i++) {
489 const char *p;
490 const struct dsdb_attribute *a;
492 p = strchr(attrs1[i], '.');
493 if (p == NULL) {
494 continue;
497 a = dsdb_attribute_by_attributeID_oid(schema, attrs1[i]);
498 if (a == NULL) {
499 continue;
502 needed = true;
503 break;
506 if (!needed) {
507 return ldb_next_request(module, req);
510 ac = talloc(req, struct resolve_oids_context);
511 if (ac == NULL) {
512 ldb_oom(ldb);
513 return LDB_ERR_OPERATIONS_ERROR;
515 ac->module = module;
516 ac->req = req;
518 tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree);
519 if (!tree) {
520 ldb_oom(ldb);
521 return LDB_ERR_OPERATIONS_ERROR;
524 schema = talloc_reference(tree, schema);
525 if (!schema) {
526 ldb_oom(ldb);
527 return LDB_ERR_OPERATIONS_ERROR;
530 ret = resolve_oids_parse_tree_replace(ldb, schema,
531 tree);
532 if (ret != LDB_SUCCESS) {
533 return ret;
536 attrs2 = str_list_copy_const(ac,
537 discard_const_p(const char *, req->op.search.attrs));
538 if (req->op.search.attrs && !attrs2) {
539 ldb_oom(ldb);
540 return LDB_ERR_OPERATIONS_ERROR;
543 for (i=0; attrs2 && attrs2[i]; i++) {
544 const char *p;
545 const struct dsdb_attribute *a;
547 p = strchr(attrs2[i], '.');
548 if (p == NULL) {
549 continue;
552 a = dsdb_attribute_by_attributeID_oid(schema, attrs2[i]);
553 if (a == NULL) {
554 continue;
557 attrs2[i] = a->lDAPDisplayName;
560 ret = ldb_build_search_req_ex(&down_req, ldb, ac,
561 req->op.search.base,
562 req->op.search.scope,
563 tree,
564 attrs2,
565 req->controls,
566 ac, resolve_oids_callback,
567 req);
568 if (ret != LDB_SUCCESS) {
569 return ret;
572 /* go on with the call chain */
573 return ldb_next_request(module, down_req);
576 static int resolve_oids_add(struct ldb_module *module, struct ldb_request *req)
578 struct ldb_context *ldb;
579 struct dsdb_schema *schema;
580 int ret;
581 struct ldb_message *msg;
582 struct ldb_request *down_req;
583 struct resolve_oids_context *ac;
585 ldb = ldb_module_get_ctx(module);
586 schema = dsdb_get_schema(ldb, NULL);
588 if (!schema) {
589 return ldb_next_request(module, req);
592 /* do not manipulate our control entries */
593 if (ldb_dn_is_special(req->op.add.message->dn)) {
594 return ldb_next_request(module, req);
597 ret = resolve_oids_message_need(ldb, schema,
598 req->op.add.message);
599 if (ret == LDB_ERR_COMPARE_FALSE) {
600 return ldb_next_request(module, req);
601 } else if (ret != LDB_ERR_COMPARE_TRUE) {
602 return ret;
605 ac = talloc(req, struct resolve_oids_context);
606 if (ac == NULL) {
607 ldb_oom(ldb);
608 return LDB_ERR_OPERATIONS_ERROR;
610 ac->module = module;
611 ac->req = req;
613 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
614 if (!msg) {
615 ldb_oom(ldb);
616 return LDB_ERR_OPERATIONS_ERROR;
619 if (!talloc_reference(msg, schema)) {
620 ldb_oom(ldb);
621 return LDB_ERR_OPERATIONS_ERROR;
624 ret = resolve_oids_message_replace(ldb, schema, msg);
625 if (ret != LDB_SUCCESS) {
626 return ret;
629 ret = ldb_build_add_req(&down_req, ldb, ac,
630 msg,
631 req->controls,
632 ac, resolve_oids_callback,
633 req);
634 if (ret != LDB_SUCCESS) {
635 return ret;
638 /* go on with the call chain */
639 return ldb_next_request(module, down_req);
642 static int resolve_oids_modify(struct ldb_module *module, struct ldb_request *req)
644 struct ldb_context *ldb;
645 struct dsdb_schema *schema;
646 int ret;
647 struct ldb_message *msg;
648 struct ldb_request *down_req;
649 struct resolve_oids_context *ac;
651 ldb = ldb_module_get_ctx(module);
652 schema = dsdb_get_schema(ldb, NULL);
654 if (!schema) {
655 return ldb_next_request(module, req);
658 /* do not manipulate our control entries */
659 if (ldb_dn_is_special(req->op.mod.message->dn)) {
660 return ldb_next_request(module, req);
663 ret = resolve_oids_message_need(ldb, schema,
664 req->op.mod.message);
665 if (ret == LDB_ERR_COMPARE_FALSE) {
666 return ldb_next_request(module, req);
667 } else if (ret != LDB_ERR_COMPARE_TRUE) {
668 return ret;
671 ac = talloc(req, struct resolve_oids_context);
672 if (ac == NULL) {
673 ldb_oom(ldb);
674 return LDB_ERR_OPERATIONS_ERROR;
676 ac->module = module;
677 ac->req = req;
679 /* we have to copy the message as the caller might have it as a const */
680 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
681 if (msg == NULL) {
682 ldb_oom(ldb);
683 return LDB_ERR_OPERATIONS_ERROR;
686 if (!talloc_reference(msg, schema)) {
687 ldb_oom(ldb);
688 return LDB_ERR_OPERATIONS_ERROR;
691 ret = resolve_oids_message_replace(ldb, schema, msg);
692 if (ret != LDB_SUCCESS) {
693 return ret;
696 ret = ldb_build_mod_req(&down_req, ldb, ac,
697 msg,
698 req->controls,
699 ac, resolve_oids_callback,
700 req);
701 if (ret != LDB_SUCCESS) {
702 return ret;
705 /* go on with the call chain */
706 return ldb_next_request(module, down_req);
709 _PUBLIC_ const struct ldb_module_ops ldb_resolve_oids_module_ops = {
710 .name = "resolve_oids",
711 .search = resolve_oids_search,
712 .add = resolve_oids_add,
713 .modify = resolve_oids_modify,