4006ccbbd7d690ea626af5dfd67b1ba8987c5363
[ira/wip.git] / source4 / lib / ldb / ldb_map / ldb_map.c
1 /* 
2    ldb database library - map backend
3
4    Copyright (C) Jelmer Vernooij 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 #include "includes.h"
26 #include "lib/ldb/include/ldb.h"
27 #include "lib/ldb/include/ldb_private.h"
28 #include "lib/ldb/ldb_map/ldb_map.h"
29
30 /* TODO:
31  *  - objectclass hint in ldb_map_attribute 
32  *     for use when multiple remote attributes (independant of each other)
33  *     map to one local attribute. E.g.: (uid, gidNumber) -> unixName
34  */
35
36 struct map_private {
37         const struct ldb_map_mappings *mappings;
38         const char *last_err_string;
39 };
40
41 /* find an attribute by the local name */
42 static const struct ldb_map_attribute *map_find_attr_local(struct ldb_module *module, const char *attr)
43 {
44         struct map_private *privdat = module->private_data;
45         int i;
46         for (i = 0; privdat->mappings->attribute_maps[i]; i++) {
47                 if (!strcmp(privdat->mappings->attribute_maps[i]->local_name, attr)) 
48                         return privdat->mappings->attribute_maps[i];
49         }
50
51         return NULL;
52 }
53
54 /* find an attribute by the remote name */
55 static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_module *module, const char *attr)
56 {
57         struct map_private *privdat = module->private_data;
58         int i;
59         for (i = 0; privdat->mappings->attribute_maps[i]; i++) {
60                 if (privdat->mappings->attribute_maps[i]->type != MAP_RENAME &&
61                         privdat->mappings->attribute_maps[i]->type != MAP_CONVERT) 
62                         continue;
63
64                 if (!strcmp(privdat->mappings->attribute_maps[i]->u.rename.remote_name, attr)) 
65                         return privdat->mappings->attribute_maps[i];
66         }
67
68         return NULL;
69 }
70
71 static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, const struct ldb_parse_tree *tree)
72 {
73         int i;
74         const struct ldb_map_attribute *attr;
75         struct ldb_parse_tree *new_tree = talloc_memdup(module, tree, sizeof(*tree));
76
77         /* Find attr in question and:
78          *  - if it has a convert_operator function, run that
79          *  - otherwise, replace attr name with required[0] */
80
81         if (tree->operation == LDB_OP_AND || 
82                 tree->operation == LDB_OP_OR) {
83                 for (i = 0; i < tree->u.list.num_elements; i++) {
84                         new_tree->u.list.elements[i] = ldb_map_parse_tree(module, tree->u.list.elements[i]);
85                 }
86
87                 return new_tree;
88         }
89                 
90         if (tree->operation == LDB_OP_NOT) {
91                 new_tree->u.isnot.child = ldb_map_parse_tree(module, tree->u.isnot.child);
92                 return new_tree;
93         }
94
95         /* tree->operation is LDB_OP_EQUALITY, LDB_OP_SUBSTRING, LDB_OP_GREATER,
96          * LDB_OP_LESS, LDB_OP_APPROX, LDB_OP_PRESENT or LDB_OP_EXTENDED
97          *
98          * (all have attr as the first element)
99          */
100
101         attr = map_find_attr_local(module, tree->u.equality.attr);
102
103         if (!attr) {
104                 DEBUG(0, ("Unable to find local attribute '%s', leaving as is", tree->u.equality.attr));
105                 return new_tree;
106         }
107
108         if (attr->type == MAP_IGNORE)
109                 return NULL;
110
111         if (attr->convert_operator) {
112                 /* Run convert_operator */
113                 talloc_free(new_tree);
114                 new_tree = attr->convert_operator(module, tree);
115         } else {
116                 new_tree->u.equality.attr = talloc_strdup(new_tree, attr->u.rename.remote_name);
117         }
118
119         return new_tree;
120 }
121
122 /* Remote DN -> Local DN */
123 static struct ldb_dn *map_remote_dn(struct ldb_module *module, const struct ldb_dn *dn)
124 {
125         struct ldb_dn *newdn;
126         int i;
127
128         newdn = talloc_memdup(module, dn, sizeof(*dn));
129         if (!newdn) 
130                 return NULL;
131
132         newdn->components = talloc_memdup(newdn, dn->components, sizeof(struct ldb_dn_component) * newdn->comp_num); 
133
134         if (!newdn->components)
135                 return NULL;
136
137         /* For each rdn, map the attribute name and possibly the 
138          * complete rdn */
139         
140         for (i = 0; i < dn->comp_num; i++) {
141                 const struct ldb_map_attribute *attr = map_find_attr_remote(module, dn->components[i].name);
142
143                 /* Unknown attribute - leave this dn as is and hope the best... */
144                 if (!attr)
145                         continue;
146
147                 if (attr->type == MAP_IGNORE) {
148                         DEBUG(0, ("Local MAP_IGNORE attribute '%s' used in DN!", dn->components[i].name));
149                         talloc_free(newdn);
150                         return NULL;
151                 }
152
153                 if (attr->type == MAP_GENERATE) {
154                         DEBUG(0, ("Local MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name));
155                         talloc_free(newdn);
156
157                         return NULL;
158                 }
159
160                 if (attr->type == MAP_CONVERT) {
161                         struct ldb_message_element elm, *newelm;
162                         struct ldb_val vals[1] = { dn->components[i].value };
163                         elm.flags = 0;
164                         elm.name = attr->u.convert.remote_name;
165                         elm.num_values = 1;
166                         elm.values = vals;
167
168                         newelm = attr->u.convert.convert_remote(module, attr->local_name, &elm);
169
170                         newdn->components[i].name = talloc_strdup(module, newelm->name);
171                         newdn->components[i].value = newelm->values[0];
172                 } else if (attr->type == MAP_RENAME) {
173                         newdn->components[i].name = talloc_strdup(module, attr->local_name);
174                 }
175         }
176         return newdn;
177 }
178
179 /* Local DN -> Remote DN */
180 static struct ldb_dn *map_local_dn(struct ldb_module *module, const struct ldb_dn *dn)
181 {       struct ldb_dn *newdn;
182         int i;
183         struct ldb_parse_tree eqtree, *new_eqtree;
184
185         newdn = talloc_memdup(module, dn, sizeof(*dn));
186         if (!newdn) 
187                 return NULL;
188
189         newdn->components = talloc_memdup(newdn, dn->components, sizeof(struct ldb_dn_component) * newdn->comp_num); 
190
191         if (!newdn->components)
192                 return NULL;
193
194         /* For each rdn, map the attribute name and possibly the 
195          * complete rdn using an equality convert_operator call */
196         
197         for (i = 0; i < dn->comp_num; i++) {
198                 const struct ldb_map_attribute *attr = map_find_attr_local(module, dn->components[i].name);
199
200                 /* Unknown attribute - leave this dn as is and hope the best... */
201                 if (!attr)
202                         continue;
203
204                 if (attr->type == MAP_IGNORE) {
205                         DEBUG(0, ("Local MAP_IGNORE attribute '%s' used in DN!", dn->components[i].name));
206                         talloc_free(newdn);
207                         return NULL;
208                 }
209
210                 if (attr->type == MAP_GENERATE) {
211                         DEBUG(0, ("Local MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name));
212                         talloc_free(newdn);
213
214                         return NULL;
215                 }
216
217                 /* Simple rename/convert only */
218                 if (attr->convert_operator) {
219                         /* Fancy stuff */
220                         eqtree.operation = LDB_OP_EQUALITY;
221                         eqtree.u.equality.attr = dn->components[i].name;
222                         eqtree.u.equality.value = dn->components[i].value;
223
224                         new_eqtree = ldb_map_parse_tree(module, &eqtree);
225
226                         /* Silently continue for now */
227                         if (!new_eqtree) {
228                                 DEBUG(0, ("Unable to convert RDN for attribute %s\n", dn->components[i].name));
229                                 continue;
230                         }
231
232                         newdn->components[i].name = new_eqtree->u.equality.attr;
233                         newdn->components[i].value = new_eqtree->u.equality.value;
234                 } else if (attr->type == MAP_CONVERT) {
235                         struct ldb_message_element elm, *newelm;
236                         struct ldb_val vals[1] = { dn->components[i].value };
237                         elm.flags = 0;
238                         elm.name = attr->local_name;
239                         elm.num_values = 1;
240                         elm.values = vals;
241
242                         newelm = attr->u.convert.convert_local(module, attr->u.convert.remote_name, &elm);
243
244                         newdn->components[i].name = talloc_strdup(module, newelm->name);
245                         newdn->components[i].value = newelm->values[0];
246                 } else if (attr->type == MAP_RENAME) {
247                         newdn->components[i].name = talloc_strdup(module, attr->u.rename.remote_name);
248                 }
249         }
250
251         return newdn;
252 }
253
254
255
256 /* Loop over ldb_map_attribute array and add remote_names */
257 static const char **ldb_map_attrs(struct ldb_module *module, const char *const attrs[])
258 {
259         int i;
260         const char **ret;
261         int ar_size = 0, last_element = 0;
262
263         /* Start with good guess of number of elements */
264         for (i = 0; attrs[i]; i++);
265
266         ret = talloc_array(module, const char *, i);
267         ar_size = i;
268
269         for (i = 0; attrs[i]; i++) {
270                 int j;
271                 const struct ldb_map_attribute *attr = map_find_attr_local(module, attrs[i]);
272
273                 if (!attr) {
274                         DEBUG(0, ("Local attribute '%s' does not have a definition!\n", attrs[i]));
275                         continue;
276                 }
277
278                 switch (attr->type)
279                 { 
280                         case MAP_IGNORE: break;
281                         case MAP_KEEP: 
282                                 if (last_element >= ar_size) {
283                                         ret = talloc_realloc(module, ret, const char *, ar_size+1);
284                                         ar_size++;
285                                 }
286                                 ret[last_element] = attr->local_name;
287                                 last_element++;
288                                 break;
289
290                         case MAP_RENAME:
291                         case MAP_CONVERT:
292                                 if (last_element >= ar_size) {
293                                         ret = talloc_realloc(module, ret, const char *, ar_size+1);
294                                         ar_size++;
295                                 }
296                                 ret[last_element] = attr->u.rename.remote_name;
297                                 last_element++;
298                                 break;
299
300                         case MAP_GENERATE:
301                                 /* Add remote_names[] for this attribute to the list of 
302                                  * attributes to request from the remote server */
303                                 for (j = 0; attr->u.generate.remote_names[j]; j++) {
304                                         if (last_element >= ar_size) {
305                                                 ret = talloc_realloc(module, ret, const char *, ar_size+1);
306                                                 ar_size++;
307                                         }
308                                         ret[last_element] = attr->u.generate.remote_names[j];                   
309                                         last_element++;
310                                 }
311                                 break;
312                 } 
313         }
314
315         return NULL;
316 }
317
318 static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, const char * const*attrs, const struct ldb_message *mi)
319 {
320         int i;
321         struct ldb_message *msg = talloc_zero(module, struct ldb_message);
322         struct ldb_message_element *elm, *oldelm;
323
324         msg->dn = map_remote_dn(module, mi->dn);
325
326         /* Loop over attrs, find in ldb_map_attribute array and 
327          * run generate() */
328
329         for (i = 0; attrs[i]; i++) {
330                 const struct ldb_map_attribute *attr = map_find_attr_local(module, attrs[i]);
331
332                 if (!attr) {
333                         DEBUG(0, ("Unable to find local attribute '%s' when generating incoming message", attrs[i]));
334                         continue;
335                 }
336
337                 switch (attr->type) {
338                         case MAP_IGNORE:break;
339                         case MAP_RENAME:
340                                 oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name);
341                                 elm = talloc_memdup(msg, oldelm, sizeof(*oldelm));
342                                 elm->name = talloc_strdup(elm, attr->local_name);
343
344                                 ldb_msg_add(module->ldb, msg, elm, 0);
345                                 break;
346                                 
347                         case MAP_CONVERT:
348                                 oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name);
349                                 elm = attr->u.convert.convert_local(msg, attr->local_name, oldelm);
350
351                                 ldb_msg_add(module->ldb, msg, elm, 0);
352                                 break;
353
354                         case MAP_KEEP:
355                                 ldb_msg_add(module->ldb, msg, ldb_msg_find_element(mi, attr->local_name), 0);
356                                 break;
357
358                         case MAP_GENERATE:
359                                 elm = attr->u.generate.generate_local(msg, attr->local_name, mi);
360                                 ldb_msg_add(module->ldb, msg, elm, 0);
361                                 break;
362                         default: 
363                                 DEBUG(0, ("Unknown attr->type for %s", attr->local_name));
364                                 break;
365                 }
366         }
367
368         return msg;
369 }
370
371 static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo)
372 {
373         struct ldb_message *msg = talloc_zero(module, struct ldb_message);
374         struct ldb_message_element *elm;
375         int i;
376         
377         msg->private_data = mo->private_data;
378         
379         msg->dn = map_local_dn(module, mo->dn);
380
381         /* Loop over mi and call generate_remote for each attribute */
382         for (i = 0; i < mo->num_elements; i++) {
383                 const struct ldb_map_attribute *attr = map_find_attr_local(module, mo->elements[i].name);
384
385                 if (!attr) {
386                         DEBUG(0, ("Undefined local attribute '%s', ignoring\n", mo->elements[i].name));
387                         continue;
388                 }
389
390                 switch (attr->type) {
391                 case MAP_IGNORE: break;
392                 case MAP_RENAME:
393                         elm = talloc_memdup(msg, &msg->elements[i], sizeof(*elm));
394                         elm->name = talloc_strdup(elm, attr->u.rename.remote_name);
395
396                         ldb_msg_add(module->ldb, msg, elm, 0);
397                         break;
398
399                 case MAP_CONVERT:
400                         elm = attr->u.convert.convert_remote(msg, attr->local_name, &msg->elements[i]);
401                         ldb_msg_add(module->ldb, msg, elm, 0);
402                         break;
403
404                 case MAP_KEEP:
405                         ldb_msg_add(module->ldb, msg, &msg->elements[i], 0);    
406                         break;
407
408                 case MAP_GENERATE:
409                         attr->u.generate.generate_remote(attr->local_name, mo, msg);
410                         break;
411                 } 
412         }
413
414         return msg;
415 }
416
417 /*
418   rename a record
419 */
420 static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
421 {
422         struct ldb_dn *n_olddn, *n_newdn;
423         int ret;
424         
425         n_olddn = map_local_dn(module, olddn);
426         n_newdn = map_local_dn(module, newdn);
427
428         ret = ldb_next_rename_record(module, n_olddn, n_newdn);
429
430         talloc_free(n_olddn);
431         talloc_free(n_newdn);
432         
433         return ret;
434 }
435
436 /*
437   delete a record
438 */
439 static int map_delete(struct ldb_module *module, const struct ldb_dn *dn)
440 {
441         struct ldb_dn *newdn;
442         int ret;
443
444         newdn = map_local_dn(module, dn);
445
446         ret = ldb_next_delete_record(module, newdn);
447
448         talloc_free(newdn);
449
450         return ret;
451 }
452
453 /*
454   search for matching records using a ldb_parse_tree
455 */
456 static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
457                               enum ldb_scope scope, struct ldb_parse_tree *tree,
458                               const char * const *attrs, struct ldb_message ***res)
459 {
460         int ret;
461         const char **newattrs;
462         struct ldb_parse_tree *new_tree;
463         struct ldb_dn *new_base;
464         struct ldb_message **newres;
465         int i;
466
467         new_tree = ldb_map_parse_tree(module, tree);
468         newattrs = ldb_map_attrs(module, attrs); 
469         new_base = map_local_dn(module, base);
470
471         ret = ldb_next_search_bytree(module, new_base, scope, new_tree, newattrs, &newres);
472
473         talloc_free(new_base);
474         talloc_free(new_tree);
475         talloc_free(newattrs);
476
477         for (i = 0; i < ret; i++) {
478                 *res[i] = ldb_map_message_incoming(module, attrs, newres[i]);
479                 talloc_free(newres[i]);
480         }
481
482         return ret;
483 }
484 /*
485   search for matching records
486 */
487 static int map_search(struct ldb_module *module, const struct ldb_dn *base,
488                        enum ldb_scope scope, const char *expression,
489                        const char * const *attrs, struct ldb_message ***res)
490 {
491         struct map_private *map = module->private_data;
492         struct ldb_parse_tree *tree;
493         int ret;
494
495         tree = ldb_parse_tree(map, expression);
496         if (tree == NULL) {
497                 map->last_err_string = "expression parse failed";
498                 return -1;
499         }
500
501         ret = map_search_bytree(module, base, scope, tree, attrs, res);
502         talloc_free(tree);
503         return ret;
504 }
505
506 /*
507   add a record
508 */
509 static int map_add(struct ldb_module *module, const struct ldb_message *msg)
510 {
511         struct ldb_message *nmsg = ldb_map_message_outgoing(module, msg);
512         int ret;
513
514         ret = ldb_next_add_record(module, nmsg);
515
516         talloc_free(nmsg);
517
518         return ret;
519 }
520
521
522
523
524 /*
525   modify a record
526 */
527 static int map_modify(struct ldb_module *module, const struct ldb_message *msg)
528 {
529         struct ldb_message *nmsg = ldb_map_message_outgoing(module, msg);
530         int ret;
531
532         ret = ldb_next_modify_record(module, nmsg);
533
534         talloc_free(nmsg);
535
536         return ret;
537 }
538
539 static int map_lock(struct ldb_module *module, const char *lockname)
540 {
541         return ldb_next_named_lock(module, lockname);
542 }
543
544 static int map_unlock(struct ldb_module *module, const char *lockname)
545 {
546         return ldb_next_named_unlock(module, lockname);
547 }
548
549 /*
550   return extended error information
551 */
552 static const char *map_errstring(struct ldb_module *module)
553 {
554         struct map_private *map = module->private_data;
555         
556         if (map->last_err_string)
557                 return map->last_err_string;
558
559         return ldb_next_errstring(module);
560 }
561
562 static const struct ldb_module_ops map_ops = {
563         .name          = "map",
564         .search        = map_search,
565         .search_bytree = map_search_bytree,
566         .add_record    = map_add,
567         .modify_record = map_modify,
568         .delete_record = map_delete,
569         .rename_record = map_rename,
570         .named_lock    = map_lock,
571         .named_unlock  = map_unlock,
572         .errstring     = map_errstring
573 };
574
575 /* the init function */
576 struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_mappings *mappings, const char *options[])
577 {
578         struct ldb_module *ctx;
579         struct map_private *data;
580
581         ctx = talloc(ldb, struct ldb_module);
582         if (!ctx)
583                 return NULL;
584
585         data = talloc(ctx, struct map_private);
586         if (!data) {
587                 talloc_free(ctx);
588                 return NULL;
589         }
590
591         data->mappings = mappings;
592         ctx->private_data = data;
593         ctx->ldb = ldb;
594         ctx->prev = ctx->next = NULL;
595         ctx->ops = &map_ops;
596
597         return ctx;
598 }