4 Copyright (C) Simo Sorce 2005
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Component: ldb attribute scoped query control module
30 * Description: this module searches all the the objects pointed
31 * by the DNs contained in the references attribute
37 #include "ldb/include/includes.h"
39 #define ASQ_CTRL_SUCCESS 0
40 #define ASQ_CTRL_INVALID_ATTRIBUTE_SYNTAX 21
41 #define ASQ_CTRL_UNWILLING_TO_PERFORM 53
42 #define ASQ_CTRL_AFFECTS_MULTIPLE_DSA 71
44 static int build_response(struct ldb_result *res, int result)
46 struct ldb_asq_control *asq;
50 for (i = 0; res->controls[i]; i++);
51 res->controls = talloc_realloc(res, res->controls, struct ldb_control *, i + 2);
54 res->controls = talloc_array(res, struct ldb_control *, 2);
56 if (res->controls == NULL)
57 return LDB_ERR_OPERATIONS_ERROR;
59 res->controls[i] = talloc(res->controls, struct ldb_control);
60 if (res->controls[i] == NULL)
61 return LDB_ERR_OPERATIONS_ERROR;
63 res->controls[i]->oid = LDB_CONTROL_ASQ_OID;
64 res->controls[i]->critical = 0;
66 asq = talloc_zero(res->controls[i], struct ldb_asq_control);
68 return LDB_ERR_OPERATIONS_ERROR;
72 res->controls[i]->data = asq;
74 res->controls[i + 1] = NULL;
80 static int asq_search(struct ldb_module *module, struct ldb_request *req)
82 struct ldb_control *control;
83 struct ldb_asq_control *asq_ctrl;
84 struct ldb_request *base_req;
85 struct ldb_message_element *el;
86 struct ldb_result *res;
90 /* check if there's a paged request control */
91 control = get_control_from_list(req->controls, LDB_CONTROL_ASQ_OID);
92 if (control == NULL) {
94 return ldb_next_request(module, req);
97 /* pre-allocate a clean result structure */
98 req->op.search.res = res = talloc_zero(req, struct ldb_result);
100 return LDB_ERR_OPERATIONS_ERROR;
102 /* check the search is well formed */
103 if (req->op.search.scope != LDB_SCOPE_BASE) {
104 return build_response(res, ASQ_CTRL_UNWILLING_TO_PERFORM);
107 asq_ctrl = talloc_get_type(control->data, struct ldb_asq_control);
109 /* get the object to retrieve the DNs to search */
110 base_req = talloc_zero(req, struct ldb_request);
111 if (base_req == NULL)
112 return LDB_ERR_OPERATIONS_ERROR;
113 base_req->operation = LDB_REQ_SEARCH;
114 base_req->op.search.base = req->op.search.base;
115 base_req->op.search.scope = LDB_SCOPE_BASE;
116 base_req->op.search.tree = req->op.search.tree;
117 base_attrs = talloc_array(base_req, char *, 2);
118 if (base_attrs == NULL)
119 return LDB_ERR_OPERATIONS_ERROR;
120 base_attrs[0] = talloc_strdup(base_attrs, asq_ctrl->source_attribute);
121 if (base_attrs[0] == NULL)
122 return LDB_ERR_OPERATIONS_ERROR;
123 base_attrs[1] = NULL;
124 base_req->op.search.attrs = (const char * const *)base_attrs;
125 base_req->creds = req->creds;
127 ret = ldb_request(module->ldb, base_req);
129 if (ret != LDB_SUCCESS)
132 /* look up the DNs */
133 el = ldb_msg_find_element(base_req->op.search.res->msgs[0],
134 asq_ctrl->source_attribute);
135 /* no values found */
137 return build_response(res, ASQ_CTRL_SUCCESS);
140 for (i = 0, c = 0; i < el->num_values; i++) {
141 struct ldb_request *exp_req;
143 exp_req = talloc_zero(req, struct ldb_request);
145 return LDB_ERR_OPERATIONS_ERROR;
146 exp_req->operation = LDB_REQ_SEARCH;
147 exp_req->op.search.base = ldb_dn_explode(exp_req, (const char *)el->values[i].data);
148 if (exp_req->op.search.base == NULL) {
149 return build_response(res, ASQ_CTRL_INVALID_ATTRIBUTE_SYNTAX);
151 exp_req->op.search.scope = LDB_SCOPE_BASE;
152 exp_req->op.search.tree = req->op.search.tree;
153 exp_req->op.search.attrs = req->op.search.attrs;
154 exp_req->creds = req->creds;
156 ret = ldb_request(module->ldb, exp_req);
158 if (ret != LDB_SUCCESS)
161 if (exp_req->op.search.res && exp_req->op.search.res->count != 0) {
162 if (res->msgs == NULL) {
163 res->msgs = talloc_array(res,
164 struct ldb_message *, 2);
166 res->msgs = talloc_realloc(res, res->msgs,
167 struct ldb_message *, c + 2);
169 if (res->msgs == NULL)
170 return LDB_ERR_OPERATIONS_ERROR;
172 res->msgs[c] = talloc_steal(res->msgs, exp_req->op.search.res->msgs[0]);
181 talloc_free(exp_req);
184 return build_response(res, ASQ_CTRL_SUCCESS);
187 static int asq(struct ldb_module *module, struct ldb_request *req)
189 switch (req->operation) {
192 return asq_search(module, req);
195 return ldb_next_request(module, req);
200 static const struct ldb_module_ops asq_ops = {
205 struct ldb_module *asq_module_init(struct ldb_context *ldb, const char *options[])
207 struct ldb_module *ctx;
209 ctx = talloc(ldb, struct ldb_module);
214 ctx->prev = ctx->next = NULL;
216 ctx->private_data = NULL;