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_replace_value(struct ldb_context *ldb,
25 struct dsdb_schema *schema,
26 const struct dsdb_attribute *a,
29 const struct dsdb_attribute *va = NULL;
30 const struct dsdb_class *vo = NULL;
34 if (a->syntax->oMSyntax != 6) {
39 p2 = memchr(valp->data, '.', valp->length);
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(schema, (char *)valp->data, valp->length);
57 return LDB_ERR_OPERATIONS_ERROR;
59 vo = dsdb_class_by_governsID_oid(schema, str);
64 *valp = data_blob_string_const(vo->lDAPDisplayName);
66 case DRSUAPI_ATTRIBUTE_systemMustContain:
67 case DRSUAPI_ATTRIBUTE_systemMayContain:
68 case DRSUAPI_ATTRIBUTE_mustContain:
69 case DRSUAPI_ATTRIBUTE_mayContain:
70 str = talloc_strndup(schema, (char *)valp->data, valp->length);
73 return LDB_ERR_OPERATIONS_ERROR;
75 va = dsdb_attribute_by_attributeID_oid(schema, str);
80 *valp = data_blob_string_const(va->lDAPDisplayName);
82 case DRSUAPI_ATTRIBUTE_governsID:
83 case DRSUAPI_ATTRIBUTE_attributeID:
84 case DRSUAPI_ATTRIBUTE_attributeSyntax:
91 static int resolve_oids_parse_tree_replace(struct ldb_context *ldb,
92 struct dsdb_schema *schema,
93 struct ldb_parse_tree *tree)
96 const struct dsdb_attribute *a = NULL;
100 struct ldb_val *valp = NULL;
103 switch (tree->operation) {
106 for (i=0;i<tree->u.list.num_elements;i++) {
107 ret = resolve_oids_parse_tree_replace(ldb, schema,
108 tree->u.list.elements[i]);
109 if (ret != LDB_SUCCESS) {
115 return resolve_oids_parse_tree_replace(ldb, schema,
116 tree->u.isnot.child);
117 case LDB_OP_EQUALITY:
121 attrp = &tree->u.equality.attr;
122 valp = &tree->u.equality.value;
124 case LDB_OP_SUBSTRING:
125 attrp = &tree->u.substring.attr;
128 attrp = &tree->u.present.attr;
130 case LDB_OP_EXTENDED:
131 attrp = &tree->u.extended.attr;
132 valp = &tree->u.extended.value;
138 p1 = strchr(*attrp, '.');
141 p2 = memchr(valp->data, '.', valp->length);
151 a = dsdb_attribute_by_attributeID_oid(schema, *attrp);
153 a = dsdb_attribute_by_lDAPDisplayName(schema, *attrp);
159 *attrp = a->lDAPDisplayName;
165 if (a->syntax->oMSyntax != 6) {
169 return resolve_oids_replace_value(ldb, schema, a, valp);
172 static int resolve_oids_element_replace(struct ldb_context *ldb,
173 struct dsdb_schema *schema,
174 struct ldb_message_element *el)
177 const struct dsdb_attribute *a = NULL;
180 p1 = strchr(el->name, '.');
183 a = dsdb_attribute_by_attributeID_oid(schema, el->name);
185 a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
191 el->name = a->lDAPDisplayName;
193 for (i=0; i < el->num_values; i++) {
195 ret = resolve_oids_replace_value(ldb, schema, a,
197 if (ret != LDB_SUCCESS) {
205 static int resolve_oids_message_replace(struct ldb_context *ldb,
206 struct dsdb_schema *schema,
207 struct ldb_message *msg)
211 for (i=0; i < msg->num_elements; i++) {
213 ret = resolve_oids_element_replace(ldb, schema,
215 if (ret != LDB_SUCCESS) {
223 struct resolve_oids_context {
224 struct ldb_module *module;
225 struct ldb_request *req;
228 static int resolve_oids_callback(struct ldb_request *req, struct ldb_reply *ares)
230 struct ldb_context *ldb;
231 struct resolve_oids_context *ac;
233 ac = talloc_get_type_abort(req->context, struct resolve_oids_context);
234 ldb = ldb_module_get_ctx(ac->module);
237 return ldb_module_done(ac->req, NULL, NULL,
238 LDB_ERR_OPERATIONS_ERROR);
240 if (ares->error != LDB_SUCCESS) {
241 return ldb_module_done(ac->req, ares->controls,
242 ares->response, ares->error);
245 switch (ares->type) {
246 case LDB_REPLY_ENTRY:
247 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
249 case LDB_REPLY_REFERRAL:
250 return ldb_module_send_referral(ac->req, ares->referral);
253 return ldb_module_done(ac->req, ares->controls,
254 ares->response, LDB_SUCCESS);
260 static int resolve_oids_search(struct ldb_module *module, struct ldb_request *req)
262 struct ldb_context *ldb;
263 struct dsdb_schema *schema;
264 struct ldb_parse_tree *tree;
265 struct ldb_request *down_req;
266 struct resolve_oids_context *ac;
269 ldb = ldb_module_get_ctx(module);
270 schema = dsdb_get_schema(ldb);
273 return ldb_next_request(module, req);
276 /* do not manipulate our control entries */
277 if (ldb_dn_is_special(req->op.search.base)) {
278 return ldb_next_request(module, req);
281 ac = talloc(req, struct resolve_oids_context);
284 return LDB_ERR_OPERATIONS_ERROR;
289 tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree);
292 return LDB_ERR_OPERATIONS_ERROR;
295 ret = resolve_oids_parse_tree_replace(ldb, schema,
297 if (ret != LDB_SUCCESS) {
301 ret = ldb_build_search_req_ex(&down_req, ldb, ac,
303 req->op.search.scope,
305 req->op.search.attrs,
307 ac, resolve_oids_callback,
309 if (ret != LDB_SUCCESS) {
313 /* go on with the call chain */
314 return ldb_next_request(module, down_req);
317 static int resolve_oids_add(struct ldb_module *module, struct ldb_request *req)
319 struct ldb_context *ldb;
320 struct dsdb_schema *schema;
322 struct ldb_message *msg;
323 struct ldb_request *down_req;
324 struct resolve_oids_context *ac;
326 ldb = ldb_module_get_ctx(module);
327 schema = dsdb_get_schema(ldb);
330 return ldb_next_request(module, req);
333 /* do not manipulate our control entries */
334 if (ldb_dn_is_special(req->op.add.message->dn)) {
335 return ldb_next_request(module, req);
338 ac = talloc(req, struct resolve_oids_context);
341 return LDB_ERR_OPERATIONS_ERROR;
346 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
349 return LDB_ERR_OPERATIONS_ERROR;
352 ret = resolve_oids_message_replace(ldb, schema, msg);
353 if (ret != LDB_SUCCESS) {
357 ret = ldb_build_add_req(&down_req, ldb, ac,
360 ac, resolve_oids_callback,
362 if (ret != LDB_SUCCESS) {
366 /* go on with the call chain */
367 return ldb_next_request(module, down_req);
370 static int resolve_oids_modify(struct ldb_module *module, struct ldb_request *req)
372 struct ldb_context *ldb;
373 struct dsdb_schema *schema;
375 struct ldb_message *msg;
376 struct ldb_request *down_req;
377 struct resolve_oids_context *ac;
379 ldb = ldb_module_get_ctx(module);
380 schema = dsdb_get_schema(ldb);
383 return ldb_next_request(module, req);
386 /* do not manipulate our control entries */
387 if (ldb_dn_is_special(req->op.mod.message->dn)) {
388 return ldb_next_request(module, req);
391 ac = talloc(req, struct resolve_oids_context);
394 return LDB_ERR_OPERATIONS_ERROR;
399 /* we have to copy the message as the caller might have it as a const */
400 msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
403 return LDB_ERR_OPERATIONS_ERROR;
406 ret = resolve_oids_message_replace(ldb, schema, msg);
407 if (ret != LDB_SUCCESS) {
411 ret = ldb_build_mod_req(&down_req, ldb, ac,
414 ac, resolve_oids_callback,
416 if (ret != LDB_SUCCESS) {
420 /* go on with the call chain */
421 return ldb_next_request(module, down_req);
424 _PUBLIC_ const struct ldb_module_ops ldb_resolve_oids_module_ops = {
425 .name = "resolve_oids",
426 .search = resolve_oids_search,
427 .add = resolve_oids_add,
428 .modify = resolve_oids_modify,