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_ATTID_objectClass
:
50 case DRSUAPI_ATTID_subClassOf
:
51 case DRSUAPI_ATTID_auxiliaryClass
:
52 case DRSUAPI_ATTID_systemPossSuperiors
:
53 case DRSUAPI_ATTID_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_ATTID_systemMustContain
:
65 case DRSUAPI_ATTID_systemMayContain
:
66 case DRSUAPI_ATTID_mustContain
:
67 case DRSUAPI_ATTID_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_ATTID_governsID
:
79 case DRSUAPI_ATTID_attributeID
:
80 case DRSUAPI_ATTID_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_ATTID_objectClass
:
237 case DRSUAPI_ATTID_subClassOf
:
238 case DRSUAPI_ATTID_auxiliaryClass
:
239 case DRSUAPI_ATTID_systemPossSuperiors
:
240 case DRSUAPI_ATTID_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_ATTID_systemMustContain
:
253 case DRSUAPI_ATTID_systemMayContain
:
254 case DRSUAPI_ATTID_mustContain
:
255 case DRSUAPI_ATTID_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_ATTID_governsID
:
268 case DRSUAPI_ATTID_attributeID
:
269 case DRSUAPI_ATTID_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 static 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
,
702 int ldb_resolve_oids_module_init(const char *version
)
704 LDB_MODULE_CHECK_VERSION(version
);
705 return ldb_register_module(&ldb_resolve_oids_module_ops
);