r12830: this can be const
[jra/samba/.git] / source4 / lib / ldb / common / ldb_modules.c
1
2 /* 
3    ldb database library
4
5    Copyright (C) Simo Sorce  2004
6
7      ** NOTE! The following LGPL license applies to the ldb
8      ** library. This does NOT imply that all of Samba is released
9      ** under the LGPL
10    
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Lesser General Public
13    License as published by the Free Software Foundation; either
14    version 2 of the License, or (at your option) any later version.
15
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Lesser General Public License for more details.
20
21    You should have received a copy of the GNU Lesser General Public
22    License along with this library; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 */
25
26 /*
27  *  Name: ldb
28  *
29  *  Component: ldb modules core
30  *
31  *  Description: core modules routines
32  *
33  *  Author: Simo Sorce
34  */
35
36 #include "includes.h"
37 #include "ldb/include/includes.h"
38
39 #define LDB_MODULE_PREFIX       "modules:"
40 #define LDB_MODULE_PREFIX_LEN   8
41
42 static char *talloc_strdup_no_spaces(struct ldb_context *ldb, const char *string)
43 {
44         int i, len;
45         char *trimmed;
46
47         trimmed = talloc_strdup(ldb, string);
48         if (!trimmed) {
49                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in talloc_strdup_trim_spaces()\n");
50                 return NULL;
51         }
52
53         len = strlen(trimmed);
54         for (i = 0; trimmed[i] != '\0'; i++) {
55                 switch (trimmed[i]) {
56                 case ' ':
57                 case '\t':
58                 case '\n':
59                         memmove(&trimmed[i], &trimmed[i + 1], len -i -1);
60                         break;
61                 }
62         }
63
64         return trimmed;
65 }
66
67
68 /* modules are called in inverse order on the stack.
69    Lets place them as an admin would think the right order is.
70    Modules order is imprtant */
71 static char **ldb_modules_list_from_string(struct ldb_context *ldb, const char *string)
72 {
73         char **modules = NULL;
74         char *modstr, *p;
75         int i;
76
77         /* spaces not admitted */
78         modstr = talloc_strdup_no_spaces(ldb, string);
79         if ( ! modstr) {
80                 return NULL;
81         }
82
83         modules = talloc_realloc(ldb, modules, char *, 2);
84         if ( ! modules ) {
85                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()\n");
86                 talloc_free(modstr);
87                 return NULL;
88         }
89         talloc_steal(modules, modstr);
90
91         i = 0;
92         while ((p = strrchr(modstr, ',')) != NULL) {
93                 *p = '\0';
94                 p++;
95                 modules[i] = p;
96
97                 i++;
98                 modules = talloc_realloc(ldb, modules, char *, i + 2);
99                 if ( ! modules ) {
100                         ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()\n");
101                         return NULL;
102                 }
103
104         }
105         modules[i] = modstr;
106
107         modules[i + 1] = NULL;
108
109         return modules;
110 }
111
112 int ldb_load_modules(struct ldb_context *ldb, const char *options[])
113 {
114         char **modules = NULL;
115         int i;
116         const struct {
117                 const char *name;
118                 ldb_module_init_t init;
119         } well_known_modules[] = {
120                 { "schema", schema_module_init },
121                 { "operational", operational_module_init },
122                 { "rdn_name", rdn_name_module_init },
123                 { "objectclass", objectclass_module_init },
124                 { "paged_results", paged_results_module_init },
125                 { "server_sort", server_sort_module_init },
126 #ifdef _SAMBA_BUILD_
127                 { "objectguid", objectguid_module_init },
128                 { "samldb", samldb_module_init },
129                 { "samba3sam", ldb_samba3sam_module_init },
130                 { "proxy", proxy_module_init },
131                 { "rootdse", rootdse_module_init },
132                 { "extended_dn", extended_dn_module_init },
133                 { "password_hash", password_hash_module_init },
134                 { "kludge_acl", kludge_acl_module_init },
135 #endif
136                 { NULL, NULL }
137         };
138
139         /* find out which modules we are requested to activate */
140
141         /* check if we have a custom module list passd as ldb option */
142         if (options) {
143                 for (i = 0; options[i] != NULL; i++) {
144                         if (strncmp(options[i], LDB_MODULE_PREFIX, LDB_MODULE_PREFIX_LEN) == 0) {
145                                 modules = ldb_modules_list_from_string(ldb, &options[i][LDB_MODULE_PREFIX_LEN]);
146                         }
147                 }
148         }
149
150         /* if not overloaded by options and the backend is not ldap try to load the modules list form ldb */
151         if ((modules == NULL) && (strcmp("ldap", ldb->modules->ops->name) != 0)) { 
152                 int ret;
153                 const char * const attrs[] = { "@LIST" , NULL};
154                 struct ldb_result *res = NULL;
155                 struct ldb_dn *mods;
156
157                 mods = ldb_dn_explode(ldb, "@MODULES");
158                 if (mods == NULL) {
159                         return -1;
160                 }
161
162                 ret = ldb_search(ldb, mods, LDB_SCOPE_BASE, "", attrs, &res);
163                 talloc_free(mods);
164                 if (ret == LDB_SUCCESS && (res->count == 0 || res->msgs[0]->num_elements == 0)) {
165                         ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db\n");
166                 } else {
167                         if (ret != LDB_SUCCESS) {
168                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for modules, bailing out\n", ldb_errstring(ldb));
169                                 return -1;
170                         }
171                         if (res->count > 1) {
172                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found (%d), bailing out\n", res->count);
173                                 talloc_free(res);
174                                 return -1;
175                         }
176
177                         modules = ldb_modules_list_from_string(ldb, 
178                                                                (const char *)res->msgs[0]->elements[0].values[0].data);
179
180                 }
181
182                 talloc_free(res);
183         }
184
185         if (modules == NULL) {
186                 ldb_debug(ldb, LDB_DEBUG_TRACE, "No modules specified for this database\n");
187                 return 0;
188         }
189
190         for (i = 0; modules[i] != NULL; i++) {
191                 struct ldb_module *current;
192                 int m;
193                 for (m=0;well_known_modules[m].name;m++) {
194                         if (strcmp(modules[i], well_known_modules[m].name) == 0) {
195                                 current = well_known_modules[m].init(ldb, options);
196                                 if (current == NULL) {
197                                         ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]);
198                                         return -1;
199                                 }
200                                 DLIST_ADD(ldb->modules, current);
201                                 break;
202                         }
203                 }
204                 if (well_known_modules[m].name == NULL) {
205                         ldb_debug(ldb, LDB_DEBUG_WARNING, "WARNING: Module [%s] not found\n", 
206                                   modules[i]);
207                 }
208         }
209
210         /* second stage init */
211         if (ldb_second_stage_init(ldb) != LDB_SUCCESS) {
212                 ldb_debug(ldb, LDB_DEBUG_ERROR, "ERROR: Second stage init failed!\n");
213                 return -1;
214         }
215
216         talloc_free(modules);
217         return 0; 
218 }
219
220 /*
221   by using this we allow ldb modules to only implement the functions they care about,
222   which makes writing a module simpler, and makes it more likely to keep working
223   when ldb is extended
224 */
225 #define FIND_OP(module, op) do { \
226         module = module->next; \
227         while (module && module->ops->op == NULL) module = module->next; \
228         if (module == NULL) return LDB_ERR_OTHER; \
229 } while (0)
230
231
232 /*
233    helper functions to call the next module in chain
234 */
235 int ldb_next_request(struct ldb_module *module, struct ldb_request *request)
236 {
237         FIND_OP(module, request);
238         return module->ops->request(module, request);
239 }
240
241 int ldb_next_second_stage_init(struct ldb_module *module)
242 {
243         FIND_OP(module, second_stage_init);
244         return module->ops->second_stage_init(module);
245 }
246
247 int ldb_next_start_trans(struct ldb_module *module)
248 {
249         FIND_OP(module, start_transaction);
250         return module->ops->start_transaction(module);
251 }
252
253 int ldb_next_end_trans(struct ldb_module *module)
254 {
255         FIND_OP(module, end_transaction);
256         return module->ops->end_transaction(module);
257 }
258
259 int ldb_next_del_trans(struct ldb_module *module)
260 {
261         FIND_OP(module, del_transaction);
262         return module->ops->del_transaction(module);
263 }
264
265 void ldb_set_errstring(struct ldb_module *module, char *err_string)
266 {
267         if (module->ldb->err_string) {
268                 talloc_free(module->ldb->err_string);
269         }
270
271         module->ldb->err_string = talloc_steal(module->ldb, err_string);
272 }
273