• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source4/dsdb/samdb/ldb_modules/
1/*
2   ldb database library
3
4   Copyright (C) Stefan Metzmacher <metze@samba.org> 2009
5
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.
10
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.
15
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/>.
18*/
19
20#include "includes.h"
21#include "ldb_module.h"
22#include "dsdb/samdb/samdb.h"
23
24static 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)
28{
29	const struct dsdb_attribute *va = NULL;
30	const struct dsdb_class *vo = NULL;
31	const void *p2;
32	char *str = NULL;
33
34	if (a->syntax->oMSyntax != 6) {
35		return LDB_ERR_COMPARE_FALSE;
36	}
37
38	if (valp) {
39		p2 = memchr(valp->data, '.', valp->length);
40	} else {
41		p2 = NULL;
42	}
43
44	if (!p2) {
45		return LDB_ERR_COMPARE_FALSE;
46	}
47
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;
58		}
59		vo = dsdb_class_by_governsID_oid(schema, str);
60		talloc_free(str);
61		if (!vo) {
62			return LDB_ERR_COMPARE_FALSE;
63		}
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;
73		}
74		va = dsdb_attribute_by_attributeID_oid(schema, str);
75		talloc_free(str);
76		if (!va) {
77			return LDB_ERR_COMPARE_FALSE;
78		}
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;
84	}
85
86	return LDB_ERR_COMPARE_FALSE;
87}
88
89static int resolve_oids_parse_tree_need(struct ldb_context *ldb,
90					struct dsdb_schema *schema,
91					const struct ldb_parse_tree *tree)
92{
93	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;
100
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;
109			}
110		}
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;
134	}
135
136	p1 = strchr(attr, '.');
137
138	if (valp) {
139		p2 = memchr(valp->data, '.', valp->length);
140	} else {
141		p2 = NULL;
142	}
143
144	if (!p1 && !p2) {
145		return LDB_ERR_COMPARE_FALSE;
146	}
147
148	if (p1) {
149		a = dsdb_attribute_by_attributeID_oid(schema, attr);
150	} else {
151		a = dsdb_attribute_by_lDAPDisplayName(schema, attr);
152	}
153	if (!a) {
154		return LDB_ERR_COMPARE_FALSE;
155	}
156
157	if (!p2) {
158		return LDB_ERR_COMPARE_FALSE;
159	}
160
161	if (a->syntax->oMSyntax != 6) {
162		return LDB_ERR_COMPARE_FALSE;
163	}
164
165	return resolve_oids_need_value(ldb, schema, a, valp);
166}
167
168static int resolve_oids_element_need(struct ldb_context *ldb,
169				     struct dsdb_schema *schema,
170				     const struct ldb_message_element *el)
171{
172	int i;
173	const struct dsdb_attribute *a = NULL;
174	const char *p1;
175
176	p1 = strchr(el->name, '.');
177
178	if (p1) {
179		a = dsdb_attribute_by_attributeID_oid(schema, el->name);
180	} else {
181		a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
182	}
183	if (!a) {
184		return LDB_ERR_COMPARE_FALSE;
185	}
186
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;
193		}
194	}
195
196	return LDB_ERR_COMPARE_FALSE;
197}
198
199static int resolve_oids_message_need(struct ldb_context *ldb,
200				     struct dsdb_schema *schema,
201				     const struct ldb_message *msg)
202{
203	int i;
204
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;
211		}
212	}
213
214	return LDB_ERR_COMPARE_FALSE;
215}
216
217static 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)
221{
222	const struct dsdb_attribute *va = NULL;
223	const struct dsdb_class *vo = NULL;
224	const void *p2;
225	char *str = NULL;
226
227	if (a->syntax->oMSyntax != 6) {
228		return LDB_SUCCESS;
229	}
230
231	if (valp) {
232		p2 = memchr(valp->data, '.', valp->length);
233	} else {
234		p2 = NULL;
235	}
236
237	if (!p2) {
238		return LDB_SUCCESS;
239	}
240
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;
251		}
252		vo = dsdb_class_by_governsID_oid(schema, str);
253		talloc_free(str);
254		if (!vo) {
255			return LDB_SUCCESS;
256		}
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;
267		}
268		va = dsdb_attribute_by_attributeID_oid(schema, str);
269		talloc_free(str);
270		if (!va) {
271			return LDB_SUCCESS;
272		}
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;
279	}
280
281	return LDB_SUCCESS;
282}
283
284static int resolve_oids_parse_tree_replace(struct ldb_context *ldb,
285					   struct dsdb_schema *schema,
286					   struct ldb_parse_tree *tree)
287{
288	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;
295
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;
304			}
305		}
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;
329	}
330
331	p1 = strchr(*attrp, '.');
332
333	if (valp) {
334		p2 = memchr(valp->data, '.', valp->length);
335	} else {
336		p2 = NULL;
337	}
338
339	if (!p1 && !p2) {
340		return LDB_SUCCESS;
341	}
342
343	if (p1) {
344		a = dsdb_attribute_by_attributeID_oid(schema, *attrp);
345	} else {
346		a = dsdb_attribute_by_lDAPDisplayName(schema, *attrp);
347	}
348	if (!a) {
349		return LDB_SUCCESS;
350	}
351
352	*attrp = a->lDAPDisplayName;
353
354	if (!p2) {
355		return LDB_SUCCESS;
356	}
357
358	if (a->syntax->oMSyntax != 6) {
359		return LDB_SUCCESS;
360	}
361
362	return resolve_oids_replace_value(ldb, schema, a, valp);
363}
364
365static int resolve_oids_element_replace(struct ldb_context *ldb,
366					struct dsdb_schema *schema,
367					struct ldb_message_element *el)
368{
369	int i;
370	const struct dsdb_attribute *a = NULL;
371	const char *p1;
372
373	p1 = strchr(el->name, '.');
374
375	if (p1) {
376		a = dsdb_attribute_by_attributeID_oid(schema, el->name);
377	} else {
378		a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
379	}
380	if (!a) {
381		return LDB_SUCCESS;
382	}
383
384	el->name = a->lDAPDisplayName;
385
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;
392		}
393	}
394
395	return LDB_SUCCESS;
396}
397
398static int resolve_oids_message_replace(struct ldb_context *ldb,
399					struct dsdb_schema *schema,
400					struct ldb_message *msg)
401{
402	int i;
403
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;
410		}
411	}
412
413	return LDB_SUCCESS;
414}
415
416struct resolve_oids_context {
417	struct ldb_module *module;
418	struct ldb_request *req;
419};
420
421static int resolve_oids_callback(struct ldb_request *req, struct ldb_reply *ares)
422{
423	struct ldb_context *ldb;
424	struct resolve_oids_context *ac;
425
426	ac = talloc_get_type_abort(req->context, struct resolve_oids_context);
427	ldb = ldb_module_get_ctx(ac->module);
428
429	if (!ares) {
430		return ldb_module_done(ac->req, NULL, NULL,
431					LDB_ERR_OPERATIONS_ERROR);
432	}
433	if (ares->error != LDB_SUCCESS) {
434		return ldb_module_done(ac->req, ares->controls,
435					ares->response, ares->error);
436	}
437
438	switch (ares->type) {
439	case LDB_REPLY_ENTRY:
440		return ldb_module_send_entry(ac->req, ares->message, ares->controls);
441
442	case LDB_REPLY_REFERRAL:
443		return ldb_module_send_referral(ac->req, ares->referral);
444
445	case LDB_REPLY_DONE:
446		return ldb_module_done(ac->req, ares->controls,
447				       ares->response, LDB_SUCCESS);
448
449	}
450	return LDB_SUCCESS;
451}
452
453static int resolve_oids_search(struct ldb_module *module, struct ldb_request *req)
454{
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
462	ldb = ldb_module_get_ctx(module);
463	schema = dsdb_get_schema(ldb);
464
465	if (!schema) {
466		return ldb_next_request(module, req);
467	}
468
469	/* do not manipulate our control entries */
470	if (ldb_dn_is_special(req->op.search.base)) {
471		return ldb_next_request(module, req);
472	}
473
474	ret = resolve_oids_parse_tree_need(ldb, schema,
475					   req->op.search.tree);
476	if (ret == LDB_ERR_COMPARE_FALSE) {
477		return ldb_next_request(module, req);
478	} else if (ret != LDB_ERR_COMPARE_TRUE) {
479		return ret;
480	}
481
482	ac = talloc(req, struct resolve_oids_context);
483	if (ac == NULL) {
484		ldb_oom(ldb);
485		return LDB_ERR_OPERATIONS_ERROR;
486	}
487	ac->module = module;
488	ac->req = req;
489
490	tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree);
491	if (!tree) {
492		ldb_oom(ldb);
493		return LDB_ERR_OPERATIONS_ERROR;
494	}
495
496	ret = resolve_oids_parse_tree_replace(ldb, schema,
497					      tree);
498	if (ret != LDB_SUCCESS) {
499		return ret;
500	}
501
502	ret = ldb_build_search_req_ex(&down_req, ldb, ac,
503				      req->op.search.base,
504				      req->op.search.scope,
505				      tree,
506				      req->op.search.attrs,
507				      req->controls,
508				      ac, resolve_oids_callback,
509				      req);
510	if (ret != LDB_SUCCESS) {
511		return ret;
512	}
513
514	/* go on with the call chain */
515	return ldb_next_request(module, down_req);
516}
517
518static int resolve_oids_add(struct ldb_module *module, struct ldb_request *req)
519{
520	struct ldb_context *ldb;
521	struct dsdb_schema *schema;
522	int ret;
523	struct ldb_message *msg;
524	struct ldb_request *down_req;
525	struct resolve_oids_context *ac;
526
527	ldb = ldb_module_get_ctx(module);
528	schema = dsdb_get_schema(ldb);
529
530	if (!schema) {
531		return ldb_next_request(module, req);
532	}
533
534	/* do not manipulate our control entries */
535	if (ldb_dn_is_special(req->op.add.message->dn)) {
536		return ldb_next_request(module, req);
537	}
538
539	ret = resolve_oids_message_need(ldb, schema,
540					req->op.add.message);
541	if (ret == LDB_ERR_COMPARE_FALSE) {
542		return ldb_next_request(module, req);
543	} else if (ret != LDB_ERR_COMPARE_TRUE) {
544		return ret;
545	}
546
547	ac = talloc(req, struct resolve_oids_context);
548	if (ac == NULL) {
549		ldb_oom(ldb);
550		return LDB_ERR_OPERATIONS_ERROR;
551	}
552	ac->module = module;
553	ac->req = req;
554
555	msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
556	if (!msg) {
557		ldb_oom(ldb);
558		return LDB_ERR_OPERATIONS_ERROR;
559	}
560
561	ret = resolve_oids_message_replace(ldb, schema, msg);
562	if (ret != LDB_SUCCESS) {
563		return ret;
564	}
565
566	ret = ldb_build_add_req(&down_req, ldb, ac,
567				msg,
568				req->controls,
569				ac, resolve_oids_callback,
570				req);
571	if (ret != LDB_SUCCESS) {
572		return ret;
573	}
574
575	/* go on with the call chain */
576	return ldb_next_request(module, down_req);
577}
578
579static int resolve_oids_modify(struct ldb_module *module, struct ldb_request *req)
580{
581	struct ldb_context *ldb;
582	struct dsdb_schema *schema;
583	int ret;
584	struct ldb_message *msg;
585	struct ldb_request *down_req;
586	struct resolve_oids_context *ac;
587
588	ldb = ldb_module_get_ctx(module);
589	schema = dsdb_get_schema(ldb);
590
591	if (!schema) {
592		return ldb_next_request(module, req);
593	}
594
595	/* do not manipulate our control entries */
596	if (ldb_dn_is_special(req->op.mod.message->dn)) {
597		return ldb_next_request(module, req);
598	}
599
600	ret = resolve_oids_message_need(ldb, schema,
601					req->op.mod.message);
602	if (ret == LDB_ERR_COMPARE_FALSE) {
603		return ldb_next_request(module, req);
604	} else if (ret != LDB_ERR_COMPARE_TRUE) {
605		return ret;
606	}
607
608	ac = talloc(req, struct resolve_oids_context);
609	if (ac == NULL) {
610		ldb_oom(ldb);
611		return LDB_ERR_OPERATIONS_ERROR;
612	}
613	ac->module = module;
614	ac->req = req;
615
616	/* we have to copy the message as the caller might have it as a const */
617	msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
618	if (msg == NULL) {
619		ldb_oom(ldb);
620		return LDB_ERR_OPERATIONS_ERROR;
621	}
622
623	ret = resolve_oids_message_replace(ldb, schema, msg);
624	if (ret != LDB_SUCCESS) {
625		return ret;
626	}
627
628	ret = ldb_build_mod_req(&down_req, ldb, ac,
629				msg,
630				req->controls,
631				ac, resolve_oids_callback,
632				req);
633	if (ret != LDB_SUCCESS) {
634		return ret;
635	}
636
637	/* go on with the call chain */
638	return ldb_next_request(module, down_req);
639}
640
641_PUBLIC_ const struct ldb_module_ops ldb_resolve_oids_module_ops = {
642	.name		= "resolve_oids",
643	.search		= resolve_oids_search,
644	.add		= resolve_oids_add,
645	.modify		= resolve_oids_modify,
646};
647
648