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
:
114 attr
= tree
->u
.equality
.attr
;
115 valp
= &tree
->u
.equality
.value
;
120 attr
= tree
->u
.comparison
.attr
;
121 valp
= &tree
->u
.comparison
.value
;
123 case LDB_OP_SUBSTRING
:
124 attr
= tree
->u
.substring
.attr
;
127 attr
= tree
->u
.present
.attr
;
129 case LDB_OP_EXTENDED
:
130 attr
= tree
->u
.extended
.attr
;
131 valp
= &tree
->u
.extended
.value
;
134 return LDB_ERR_COMPARE_FALSE
;
137 p1
= strchr(attr
, '.');
140 p2
= memchr(valp
->data
, '.', valp
->length
);
146 return LDB_ERR_COMPARE_FALSE
;
150 a
= dsdb_attribute_by_attributeID_oid(schema
, attr
);
152 a
= dsdb_attribute_by_lDAPDisplayName(schema
, attr
);
155 return LDB_ERR_COMPARE_FALSE
;
159 return LDB_ERR_COMPARE_FALSE
;
162 return resolve_oids_need_value(ldb
, schema
, a
, valp
);
165 static int resolve_oids_element_need(struct ldb_context
*ldb
,
166 struct dsdb_schema
*schema
,
167 const struct ldb_message_element
*el
)
170 const struct dsdb_attribute
*a
= NULL
;
173 p1
= strchr(el
->name
, '.');
176 a
= dsdb_attribute_by_attributeID_oid(schema
, el
->name
);
178 a
= dsdb_attribute_by_lDAPDisplayName(schema
, el
->name
);
181 return LDB_ERR_COMPARE_FALSE
;
184 for (i
=0; i
< el
->num_values
; i
++) {
186 ret
= resolve_oids_need_value(ldb
, schema
, a
,
188 if (ret
!= LDB_ERR_COMPARE_FALSE
) {
193 return LDB_ERR_COMPARE_FALSE
;
196 static int resolve_oids_message_need(struct ldb_context
*ldb
,
197 struct dsdb_schema
*schema
,
198 const struct ldb_message
*msg
)
202 for (i
=0; i
< msg
->num_elements
; i
++) {
204 ret
= resolve_oids_element_need(ldb
, schema
,
206 if (ret
!= LDB_ERR_COMPARE_FALSE
) {
211 return LDB_ERR_COMPARE_FALSE
;
214 static int resolve_oids_replace_value(struct ldb_context
*ldb
,
215 struct dsdb_schema
*schema
,
216 const struct dsdb_attribute
*a
,
217 struct ldb_val
*valp
)
219 const struct dsdb_attribute
*va
= NULL
;
220 const struct dsdb_class
*vo
= NULL
;
224 if (a
->syntax
->oMSyntax
!= 6) {
229 p2
= memchr(valp
->data
, '.', valp
->length
);
238 switch (a
->attributeID_id
) {
239 case DRSUAPI_ATTID_objectClass
:
240 case DRSUAPI_ATTID_subClassOf
:
241 case DRSUAPI_ATTID_auxiliaryClass
:
242 case DRSUAPI_ATTID_systemPossSuperiors
:
243 case DRSUAPI_ATTID_possSuperiors
:
244 str
= talloc_strndup(schema
, (char *)valp
->data
, valp
->length
);
248 vo
= dsdb_class_by_governsID_oid(schema
, str
);
253 *valp
= data_blob_string_const(vo
->lDAPDisplayName
);
255 case DRSUAPI_ATTID_systemMustContain
:
256 case DRSUAPI_ATTID_systemMayContain
:
257 case DRSUAPI_ATTID_mustContain
:
258 case DRSUAPI_ATTID_mayContain
:
259 str
= talloc_strndup(schema
, (char *)valp
->data
, valp
->length
);
263 va
= dsdb_attribute_by_attributeID_oid(schema
, str
);
268 *valp
= data_blob_string_const(va
->lDAPDisplayName
);
270 case DRSUAPI_ATTID_governsID
:
271 case DRSUAPI_ATTID_attributeID
:
272 case DRSUAPI_ATTID_attributeSyntax
:
279 static int resolve_oids_parse_tree_replace(struct ldb_context
*ldb
,
280 struct dsdb_schema
*schema
,
281 struct ldb_parse_tree
*tree
)
284 const struct dsdb_attribute
*a
= NULL
;
288 struct ldb_val
*valp
= NULL
;
291 switch (tree
->operation
) {
294 for (i
=0;i
<tree
->u
.list
.num_elements
;i
++) {
295 ret
= resolve_oids_parse_tree_replace(ldb
, schema
,
296 tree
->u
.list
.elements
[i
]);
297 if (ret
!= LDB_SUCCESS
) {
303 return resolve_oids_parse_tree_replace(ldb
, schema
,
304 tree
->u
.isnot
.child
);
305 case LDB_OP_EQUALITY
:
306 attrp
= &tree
->u
.equality
.attr
;
307 valp
= &tree
->u
.equality
.value
;
312 attrp
= &tree
->u
.comparison
.attr
;
313 valp
= &tree
->u
.comparison
.value
;
315 case LDB_OP_SUBSTRING
:
316 attrp
= &tree
->u
.substring
.attr
;
319 attrp
= &tree
->u
.present
.attr
;
321 case LDB_OP_EXTENDED
:
322 attrp
= &tree
->u
.extended
.attr
;
323 valp
= &tree
->u
.extended
.value
;
329 p1
= strchr(*attrp
, '.');
332 p2
= memchr(valp
->data
, '.', valp
->length
);
342 a
= dsdb_attribute_by_attributeID_oid(schema
, *attrp
);
344 a
= dsdb_attribute_by_lDAPDisplayName(schema
, *attrp
);
350 *attrp
= a
->lDAPDisplayName
;
356 if (a
->syntax
->oMSyntax
!= 6) {
360 return resolve_oids_replace_value(ldb
, schema
, a
, valp
);
363 static int resolve_oids_element_replace(struct ldb_context
*ldb
,
364 struct dsdb_schema
*schema
,
365 struct ldb_message_element
*el
)
368 const struct dsdb_attribute
*a
= NULL
;
371 p1
= strchr(el
->name
, '.');
374 a
= dsdb_attribute_by_attributeID_oid(schema
, el
->name
);
376 a
= dsdb_attribute_by_lDAPDisplayName(schema
, el
->name
);
382 el
->name
= a
->lDAPDisplayName
;
384 for (i
=0; i
< el
->num_values
; i
++) {
386 ret
= resolve_oids_replace_value(ldb
, schema
, a
,
388 if (ret
!= LDB_SUCCESS
) {
396 static int resolve_oids_message_replace(struct ldb_context
*ldb
,
397 struct dsdb_schema
*schema
,
398 struct ldb_message
*msg
)
402 for (i
=0; i
< msg
->num_elements
; i
++) {
404 ret
= resolve_oids_element_replace(ldb
, schema
,
406 if (ret
!= LDB_SUCCESS
) {
414 struct resolve_oids_context
{
415 struct ldb_module
*module
;
416 struct ldb_request
*req
;
419 static int resolve_oids_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
421 struct resolve_oids_context
*ac
;
423 ac
= talloc_get_type_abort(req
->context
, struct resolve_oids_context
);
426 return ldb_module_done(ac
->req
, NULL
, NULL
,
427 LDB_ERR_OPERATIONS_ERROR
);
429 if (ares
->error
!= LDB_SUCCESS
) {
430 return ldb_module_done(ac
->req
, ares
->controls
,
431 ares
->response
, ares
->error
);
434 switch (ares
->type
) {
435 case LDB_REPLY_ENTRY
:
436 return ldb_module_send_entry(ac
->req
, ares
->message
, ares
->controls
);
438 case LDB_REPLY_REFERRAL
:
439 return ldb_module_send_referral(ac
->req
, ares
->referral
);
442 return ldb_module_done(ac
->req
, ares
->controls
,
443 ares
->response
, LDB_SUCCESS
);
449 static int resolve_oids_search(struct ldb_module
*module
, struct ldb_request
*req
)
451 struct ldb_context
*ldb
;
452 struct dsdb_schema
*schema
;
453 struct ldb_parse_tree
*tree
;
454 struct ldb_request
*down_req
;
455 struct resolve_oids_context
*ac
;
458 const char * const *attrs1
;
462 ldb
= ldb_module_get_ctx(module
);
463 schema
= dsdb_get_schema(ldb
, NULL
);
466 return ldb_next_request(module
, req
);
469 /* do not manipulate our control entries */
470 if (ldb_dn_is_special(req
->op
.search
.base
)) {
471 return ldb_next_request(module
, req
);
474 ret
= resolve_oids_parse_tree_need(ldb
, schema
,
475 req
->op
.search
.tree
);
476 if (ret
== LDB_ERR_COMPARE_TRUE
) {
478 } else if (ret
!= LDB_ERR_COMPARE_FALSE
) {
482 attrs1
= req
->op
.search
.attrs
;
484 for (i
=0; attrs1
&& attrs1
[i
]; i
++) {
486 const struct dsdb_attribute
*a
;
488 p
= strchr(attrs1
[i
], '.');
493 a
= dsdb_attribute_by_attributeID_oid(schema
, attrs1
[i
]);
503 return ldb_next_request(module
, req
);
506 ac
= talloc(req
, struct resolve_oids_context
);
513 tree
= ldb_parse_tree_copy_shallow(ac
, req
->op
.search
.tree
);
518 schema
= talloc_reference(tree
, schema
);
523 ret
= resolve_oids_parse_tree_replace(ldb
, schema
,
525 if (ret
!= LDB_SUCCESS
) {
529 attrs2
= str_list_copy_const(ac
,
530 discard_const_p(const char *, req
->op
.search
.attrs
));
531 if (req
->op
.search
.attrs
&& !attrs2
) {
535 for (i
=0; attrs2
&& attrs2
[i
]; i
++) {
537 const struct dsdb_attribute
*a
;
539 p
= strchr(attrs2
[i
], '.');
544 a
= dsdb_attribute_by_attributeID_oid(schema
, attrs2
[i
]);
549 attrs2
[i
] = a
->lDAPDisplayName
;
552 ret
= ldb_build_search_req_ex(&down_req
, ldb
, ac
,
554 req
->op
.search
.scope
,
558 ac
, resolve_oids_callback
,
560 LDB_REQ_SET_LOCATION(down_req
);
561 if (ret
!= LDB_SUCCESS
) {
565 /* go on with the call chain */
566 return ldb_next_request(module
, down_req
);
569 static int resolve_oids_add(struct ldb_module
*module
, struct ldb_request
*req
)
571 struct ldb_context
*ldb
;
572 struct dsdb_schema
*schema
;
574 struct ldb_message
*msg
;
575 struct ldb_request
*down_req
;
576 struct resolve_oids_context
*ac
;
578 ldb
= ldb_module_get_ctx(module
);
579 schema
= dsdb_get_schema(ldb
, NULL
);
582 return ldb_next_request(module
, req
);
585 /* do not manipulate our control entries */
586 if (ldb_dn_is_special(req
->op
.add
.message
->dn
)) {
587 return ldb_next_request(module
, req
);
590 ret
= resolve_oids_message_need(ldb
, schema
,
591 req
->op
.add
.message
);
592 if (ret
== LDB_ERR_COMPARE_FALSE
) {
593 return ldb_next_request(module
, req
);
594 } else if (ret
!= LDB_ERR_COMPARE_TRUE
) {
598 ac
= talloc(req
, struct resolve_oids_context
);
605 msg
= ldb_msg_copy_shallow(ac
, ac
->req
->op
.add
.message
);
610 if (!talloc_reference(msg
, schema
)) {
614 ret
= resolve_oids_message_replace(ldb
, schema
, msg
);
615 if (ret
!= LDB_SUCCESS
) {
619 ret
= ldb_build_add_req(&down_req
, ldb
, ac
,
622 ac
, resolve_oids_callback
,
624 LDB_REQ_SET_LOCATION(down_req
);
625 if (ret
!= LDB_SUCCESS
) {
629 /* go on with the call chain */
630 return ldb_next_request(module
, down_req
);
633 static int resolve_oids_modify(struct ldb_module
*module
, struct ldb_request
*req
)
635 struct ldb_context
*ldb
;
636 struct dsdb_schema
*schema
;
638 struct ldb_message
*msg
;
639 struct ldb_request
*down_req
;
640 struct resolve_oids_context
*ac
;
642 ldb
= ldb_module_get_ctx(module
);
643 schema
= dsdb_get_schema(ldb
, NULL
);
646 return ldb_next_request(module
, req
);
649 /* do not manipulate our control entries */
650 if (ldb_dn_is_special(req
->op
.mod
.message
->dn
)) {
651 return ldb_next_request(module
, req
);
654 ret
= resolve_oids_message_need(ldb
, schema
,
655 req
->op
.mod
.message
);
656 if (ret
== LDB_ERR_COMPARE_FALSE
) {
657 return ldb_next_request(module
, req
);
658 } else if (ret
!= LDB_ERR_COMPARE_TRUE
) {
662 ac
= talloc(req
, struct resolve_oids_context
);
669 /* we have to copy the message as the caller might have it as a const */
670 msg
= ldb_msg_copy_shallow(ac
, req
->op
.mod
.message
);
675 if (!talloc_reference(msg
, schema
)) {
679 ret
= resolve_oids_message_replace(ldb
, schema
, msg
);
680 if (ret
!= LDB_SUCCESS
) {
684 ret
= ldb_build_mod_req(&down_req
, ldb
, ac
,
687 ac
, resolve_oids_callback
,
689 LDB_REQ_SET_LOCATION(down_req
);
690 if (ret
!= LDB_SUCCESS
) {
694 /* go on with the call chain */
695 return ldb_next_request(module
, down_req
);
698 static const struct ldb_module_ops ldb_resolve_oids_module_ops
= {
699 .name
= "resolve_oids",
700 .search
= resolve_oids_search
,
701 .add
= resolve_oids_add
,
702 .modify
= resolve_oids_modify
,
706 int ldb_resolve_oids_module_init(const char *version
)
708 LDB_MODULE_CHECK_VERSION(version
);
709 return ldb_register_module(&ldb_resolve_oids_module_ops
);