r12948: fix compiler warning
[metze/samba/wip.git] / source4 / lib / ldb / modules / asq.c
1 /* 
2    ldb database library
3
4    Copyright (C) Simo Sorce  2005
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
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.
14
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.
19
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
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb attribute scoped query control module
29  *
30  *  Description: this module searches all the the objects pointed
31  *               by the DNs contained in the references attribute
32  *
33  *  Author: Simo Sorce
34  */
35
36 #include "includes.h"
37 #include "ldb/include/includes.h"
38
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
43
44 static int build_response(struct ldb_result *res, int result)
45 {
46         struct ldb_asq_control *asq;
47         int i;
48
49         if (res->controls) {
50                 for (i = 0; res->controls[i]; i++);
51                 res->controls = talloc_realloc(res, res->controls, struct ldb_control *, i + 2);
52         } else {
53                 i = 0;
54                 res->controls = talloc_array(res, struct ldb_control *, 2);
55         }
56         if (res->controls == NULL)
57                 return LDB_ERR_OPERATIONS_ERROR;
58
59         res->controls[i] = talloc(res->controls, struct ldb_control);
60         if (res->controls[i] == NULL)
61                 return LDB_ERR_OPERATIONS_ERROR;
62
63         res->controls[i]->oid = LDB_CONTROL_ASQ_OID;
64         res->controls[i]->critical = 0;
65
66         asq = talloc_zero(res->controls[i], struct ldb_asq_control);
67         if (asq == NULL)
68                 return LDB_ERR_OPERATIONS_ERROR;
69
70         asq->result = result;
71         
72         res->controls[i]->data = asq;
73
74         res->controls[i + 1] = NULL;
75
76         return LDB_SUCCESS;
77 }
78
79 /* search */
80 static int asq_search(struct ldb_module *module, struct ldb_request *req)
81 {
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;
87         char **base_attrs;
88         int i, c, ret;
89
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) {
93                 /* not found go on */
94                 return ldb_next_request(module, req);
95         }
96
97         /* pre-allocate a clean result structure */
98         req->op.search.res = res = talloc_zero(req, struct ldb_result);
99         if (res == NULL)
100                 return LDB_ERR_OPERATIONS_ERROR;
101
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);
105         }
106
107         asq_ctrl = talloc_get_type(control->data, struct ldb_asq_control);
108
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;
126
127         ret = ldb_request(module->ldb, base_req);
128
129         if (ret != LDB_SUCCESS)
130                 return ret;
131
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 */
136         if (el == NULL) {
137                 return build_response(res, ASQ_CTRL_SUCCESS);
138         }
139
140         for (i = 0, c = 0; i < el->num_values; i++) {
141                 struct ldb_request *exp_req;
142
143                 exp_req = talloc_zero(req, struct ldb_request);
144                 if (exp_req == NULL)
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);
150                 }
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;
155
156                 ret = ldb_request(module->ldb, exp_req);
157
158                 if (ret != LDB_SUCCESS)
159                         return ret;
160
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);
165                         } else {
166                                 res->msgs = talloc_realloc(res, res->msgs,
167                                                 struct ldb_message *, c + 2);
168                         }
169                         if (res->msgs == NULL)
170                                 return LDB_ERR_OPERATIONS_ERROR;
171
172                         res->msgs[c] = talloc_steal(res->msgs, exp_req->op.search.res->msgs[0]);
173                         c++;
174                 }
175
176                 if (res->msgs) {
177                         res->msgs[c] = NULL;
178                         res->count = c;
179                 }
180
181                 talloc_free(exp_req);
182         }
183
184         return build_response(res, ASQ_CTRL_SUCCESS);
185 }
186
187 static int asq(struct ldb_module *module, struct ldb_request *req)
188 {
189         switch (req->operation) {
190
191         case LDB_REQ_SEARCH:
192                 return asq_search(module, req);
193
194         default:
195                 return ldb_next_request(module, req);
196
197         }
198 }
199
200 static const struct ldb_module_ops asq_ops = {
201         .name              = "asq",
202         .request           = asq
203 };
204
205 struct ldb_module *asq_module_init(struct ldb_context *ldb, const char *options[])
206 {
207         struct ldb_module *ctx;
208
209         ctx = talloc(ldb, struct ldb_module);
210         if (!ctx)
211                 return NULL;
212
213         ctx->ldb = ldb;
214         ctx->prev = ctx->next = NULL;
215         ctx->ops = &asq_ops;
216         ctx->private_data = NULL;
217
218         return ctx;
219 }