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
);
57 return LDB_ERR_OPERATIONS_ERROR
;
59 vo
= dsdb_class_by_governsID_oid(schema
, str
);
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
);
72 return LDB_ERR_OPERATIONS_ERROR
;
74 va
= dsdb_attribute_by_attributeID_oid(schema
, str
);
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
)
94 const struct dsdb_attribute
*a
= NULL
;
98 const struct ldb_val
*valp
= NULL
;
101 switch (tree
->operation
) {
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
) {
111 return LDB_ERR_COMPARE_FALSE
;
113 return resolve_oids_parse_tree_need(ldb
, schema
,
114 tree
->u
.isnot
.child
);
115 case LDB_OP_EQUALITY
:
119 attr
= tree
->u
.equality
.attr
;
120 valp
= &tree
->u
.equality
.value
;
122 case LDB_OP_SUBSTRING
:
123 attr
= tree
->u
.substring
.attr
;
126 attr
= tree
->u
.present
.attr
;
128 case LDB_OP_EXTENDED
:
129 attr
= tree
->u
.extended
.attr
;
130 valp
= &tree
->u
.extended
.value
;
133 return LDB_ERR_COMPARE_FALSE
;
136 p1
= strchr(attr
, '.');
139 p2
= memchr(valp
->data
, '.', valp
->length
);
145 return LDB_ERR_COMPARE_FALSE
;
149 a
= dsdb_attribute_by_attributeID_oid(schema
, attr
);
151 a
= dsdb_attribute_by_lDAPDisplayName(schema
, attr
);
154 return LDB_ERR_COMPARE_FALSE
;
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
)
173 const struct dsdb_attribute
*a
= NULL
;
176 p1
= strchr(el
->name
, '.');
179 a
= dsdb_attribute_by_attributeID_oid(schema
, el
->name
);
181 a
= dsdb_attribute_by_lDAPDisplayName(schema
, el
->name
);
184 return LDB_ERR_COMPARE_FALSE
;
187 for (i
=0; i
< el
->num_values
; i
++) {
189 ret
= resolve_oids_need_value(ldb
, schema
, a
,
191 if (ret
!= LDB_ERR_COMPARE_FALSE
) {
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
)
205 for (i
=0; i
< msg
->num_elements
; i
++) {
207 ret
= resolve_oids_element_need(ldb
, schema
,
209 if (ret
!= LDB_ERR_COMPARE_FALSE
) {
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
;
227 if (a
->syntax
->oMSyntax
!= 6) {
232 p2
= memchr(valp
->data
, '.', valp
->length
);
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
);
250 return LDB_ERR_OPERATIONS_ERROR
;
252 vo
= dsdb_class_by_governsID_oid(schema
, str
);
257 *valp
= data_blob_string_const(vo
->lDAPDisplayName
);
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
);
266 return LDB_ERR_OPERATIONS_ERROR
;
268 va
= dsdb_attribute_by_attributeID_oid(schema
, str
);
273 *valp
= data_blob_string_const(va
->lDAPDisplayName
);
275 case DRSUAPI_ATTRIBUTE_governsID
:
276 case DRSUAPI_ATTRIBUTE_attributeID
:
277 case DRSUAPI_ATTRIBUTE_attributeSyntax
:
284 static int resolve_oids_parse_tree_replace(struct ldb_context
*ldb
,
285 struct dsdb_schema
*schema
,
286 struct ldb_parse_tree
*tree
)
289 const struct dsdb_attribute
*a
= NULL
;
293 struct ldb_val
*valp
= NULL
;
296 switch (tree
->operation
) {
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
) {
308 return resolve_oids_parse_tree_replace(ldb
, schema
,
309 tree
->u
.isnot
.child
);
310 case LDB_OP_EQUALITY
:
314 attrp
= &tree
->u
.equality
.attr
;
315 valp
= &tree
->u
.equality
.value
;
317 case LDB_OP_SUBSTRING
:
318 attrp
= &tree
->u
.substring
.attr
;
321 attrp
= &tree
->u
.present
.attr
;
323 case LDB_OP_EXTENDED
:
324 attrp
= &tree
->u
.extended
.attr
;
325 valp
= &tree
->u
.extended
.value
;
331 p1
= strchr(*attrp
, '.');
334 p2
= memchr(valp
->data
, '.', valp
->length
);
344 a
= dsdb_attribute_by_attributeID_oid(schema
, *attrp
);
346 a
= dsdb_attribute_by_lDAPDisplayName(schema
, *attrp
);
352 *attrp
= a
->lDAPDisplayName
;
358 if (a
->syntax
->oMSyntax
!= 6) {
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
)
370 const struct dsdb_attribute
*a
= NULL
;
373 p1
= strchr(el
->name
, '.');
376 a
= dsdb_attribute_by_attributeID_oid(schema
, el
->name
);
378 a
= dsdb_attribute_by_lDAPDisplayName(schema
, el
->name
);
384 el
->name
= a
->lDAPDisplayName
;
386 for (i
=0; i
< el
->num_values
; i
++) {
388 ret
= resolve_oids_replace_value(ldb
, schema
, a
,
390 if (ret
!= LDB_SUCCESS
) {
398 static int resolve_oids_message_replace(struct ldb_context
*ldb
,
399 struct dsdb_schema
*schema
,
400 struct ldb_message
*msg
)
404 for (i
=0; i
< msg
->num_elements
; i
++) {
406 ret
= resolve_oids_element_replace(ldb
, schema
,
408 if (ret
!= 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
);
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
);
446 return ldb_module_done(ac
->req
, ares
->controls
,
447 ares
->response
, 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
;
462 const char * const *attrs1
;
466 ldb
= ldb_module_get_ctx(module
);
467 schema
= dsdb_get_schema(ldb
, NULL
);
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
) {
482 } else if (ret
!= LDB_ERR_COMPARE_FALSE
) {
486 attrs1
= req
->op
.search
.attrs
;
488 for (i
=0; attrs1
&& attrs1
[i
]; i
++) {
490 const struct dsdb_attribute
*a
;
492 p
= strchr(attrs1
[i
], '.');
497 a
= dsdb_attribute_by_attributeID_oid(schema
, attrs1
[i
]);
507 return ldb_next_request(module
, req
);
510 ac
= talloc(req
, struct resolve_oids_context
);
513 return LDB_ERR_OPERATIONS_ERROR
;
518 tree
= ldb_parse_tree_copy_shallow(ac
, req
->op
.search
.tree
);
521 return LDB_ERR_OPERATIONS_ERROR
;
524 schema
= talloc_reference(tree
, schema
);
527 return LDB_ERR_OPERATIONS_ERROR
;
530 ret
= resolve_oids_parse_tree_replace(ldb
, schema
,
532 if (ret
!= LDB_SUCCESS
) {
536 attrs2
= str_list_copy_const(ac
,
537 discard_const_p(const char *, req
->op
.search
.attrs
));
538 if (req
->op
.search
.attrs
&& !attrs2
) {
540 return LDB_ERR_OPERATIONS_ERROR
;
543 for (i
=0; attrs2
&& attrs2
[i
]; i
++) {
545 const struct dsdb_attribute
*a
;
547 p
= strchr(attrs2
[i
], '.');
552 a
= dsdb_attribute_by_attributeID_oid(schema
, attrs2
[i
]);
557 attrs2
[i
] = a
->lDAPDisplayName
;
560 ret
= ldb_build_search_req_ex(&down_req
, ldb
, ac
,
562 req
->op
.search
.scope
,
566 ac
, resolve_oids_callback
,
568 if (ret
!= LDB_SUCCESS
) {
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
;
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
);
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
) {
605 ac
= talloc(req
, struct resolve_oids_context
);
608 return LDB_ERR_OPERATIONS_ERROR
;
613 msg
= ldb_msg_copy_shallow(ac
, ac
->req
->op
.add
.message
);
616 return LDB_ERR_OPERATIONS_ERROR
;
619 if (!talloc_reference(msg
, schema
)) {
621 return LDB_ERR_OPERATIONS_ERROR
;
624 ret
= resolve_oids_message_replace(ldb
, schema
, msg
);
625 if (ret
!= LDB_SUCCESS
) {
629 ret
= ldb_build_add_req(&down_req
, ldb
, ac
,
632 ac
, resolve_oids_callback
,
634 if (ret
!= LDB_SUCCESS
) {
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
;
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
);
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
) {
671 ac
= talloc(req
, struct resolve_oids_context
);
674 return LDB_ERR_OPERATIONS_ERROR
;
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
);
683 return LDB_ERR_OPERATIONS_ERROR
;
686 if (!talloc_reference(msg
, schema
)) {
688 return LDB_ERR_OPERATIONS_ERROR
;
691 ret
= resolve_oids_message_replace(ldb
, schema
, msg
);
692 if (ret
!= LDB_SUCCESS
) {
696 ret
= ldb_build_mod_req(&down_req
, ldb
, ac
,
699 ac
, resolve_oids_callback
,
701 if (ret
!= LDB_SUCCESS
) {
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
,