]> git.sur5r.net Git - openldap/blob - servers/slapd/overlays/rwmmap.c
add rwm overlay configure and make stuff (need autoconf/autoheader ...)
[openldap] / servers / slapd / overlays / rwmmap.c
1 /* rwmmap.c - rewrite/mapping routines */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1999-2003 The OpenLDAP Foundation.
6  * Portions Copyright 1999-2003 Howard Chu.
7  * Portions Copyright 2000-2003 Pierangelo Masarati.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS:
19  * This work was initially developed by the Howard Chu for inclusion
20  * in OpenLDAP Software and subsequently enhanced by Pierangelo
21  * Masarati.
22  */
23
24 #include "portable.h"
25
26 #ifdef SLAPD_OVER_RWM
27
28 #include <stdio.h>
29
30 #include <ac/string.h>
31 #include <ac/socket.h>
32
33 #include "slap.h"
34 #include "rwm.h"
35
36 #undef ldap_debug       /* silence a warning in ldap-int.h */
37 #include "../../../libraries/libldap/ldap-int.h"
38
39 int
40 mapping_cmp ( const void *c1, const void *c2 )
41 {
42         struct ldapmapping *map1 = (struct ldapmapping *)c1;
43         struct ldapmapping *map2 = (struct ldapmapping *)c2;
44         int rc = map1->src.bv_len - map2->src.bv_len;
45         if (rc) return rc;
46         return ( strcasecmp(map1->src.bv_val, map2->src.bv_val) );
47 }
48
49 int
50 mapping_dup ( void *c1, void *c2 )
51 {
52         struct ldapmapping *map1 = (struct ldapmapping *)c1;
53         struct ldapmapping *map2 = (struct ldapmapping *)c2;
54
55         return( ( strcasecmp(map1->src.bv_val, map2->src.bv_val) == 0 ) ? -1 : 0 );
56 }
57
58 void
59 rwm_map_init ( struct ldapmap *lm, struct ldapmapping **m )
60 {
61         struct ldapmapping *mapping;
62
63         assert( m );
64
65         *m = NULL;
66         
67         mapping = (struct ldapmapping *)ch_calloc( 2, 
68                         sizeof( struct ldapmapping ) );
69         if ( mapping == NULL ) {
70                 return;
71         }
72
73         ber_str2bv( "objectclass", sizeof("objectclass")-1, 1, &mapping->src);
74         ber_dupbv( &mapping->dst, &mapping->src );
75         mapping[1].src = mapping->src;
76         mapping[1].dst = mapping->dst;
77
78         avl_insert( &lm->map, (caddr_t)mapping, 
79                         mapping_cmp, mapping_dup );
80         avl_insert( &lm->remap, (caddr_t)&mapping[1], 
81                         mapping_cmp, mapping_dup );
82         *m = mapping;
83 }
84
85 void
86 rwm_map ( struct ldapmap *map, struct berval *s, struct berval *bv,
87         int remap )
88 {
89         Avlnode *tree;
90         struct ldapmapping *mapping, fmapping;
91
92         if (remap == BACKLDAP_REMAP)
93                 tree = map->remap;
94         else
95                 tree = map->map;
96
97         bv->bv_len = 0;
98         bv->bv_val = NULL;
99         fmapping.src = *s;
100         mapping = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp );
101         if (mapping != NULL) {
102                 if ( mapping->dst.bv_val )
103                         *bv = mapping->dst;
104                 return;
105         }
106
107         if (!map->drop_missing)
108                 *bv = *s;
109
110         return;
111 }
112
113 int
114 rwm_map_attrs(
115                 struct ldapmap *at_map,
116                 AttributeName *an,
117                 int remap,
118                 char ***mapped_attrs
119 )
120 {
121         int i, j;
122         char **na;
123         struct berval mapped;
124
125         if (an == NULL) {
126                 *mapped_attrs = NULL;
127                 return LDAP_SUCCESS;
128         }
129
130         for (i = 0; an[i].an_name.bv_val; i++) {
131                 /*  */
132         }
133
134         na = (char **)ch_calloc( i + 1, sizeof(char *) );
135         if (na == NULL) {
136                 *mapped_attrs = NULL;
137                 return LDAP_NO_MEMORY;
138         }
139
140         for (i = j = 0; an[i].an_name.bv_val; i++) {
141                 rwm_map(at_map, &an[i].an_name, &mapped, remap);
142                 if (mapped.bv_val != NULL && mapped.bv_val != '\0')
143                         na[j++] = mapped.bv_val;
144         }
145         if (j == 0 && i != 0)
146                 na[j++] = LDAP_NO_ATTRS;
147         na[j] = NULL;
148
149         *mapped_attrs = na;
150         return LDAP_SUCCESS;
151 }
152
153 int
154 map_attr_value(
155                 dncookie                *dc,
156                 AttributeDescription    *ad,
157                 struct berval           *mapped_attr,
158                 struct berval           *value,
159                 struct berval           *mapped_value,
160                 int                     remap )
161 {
162         struct berval           vtmp;
163         int                     freeval = 0;
164
165         rwm_map( &dc->rwmap->rwm_at, &ad->ad_cname, mapped_attr, remap );
166         if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
167                 /*
168                  * FIXME: are we sure we need to search oc_map if at_map fails?
169                  */
170                 rwm_map( &dc->rwmap->rwm_oc, &ad->ad_cname, mapped_attr, remap );
171                 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
172                         *mapped_attr = ad->ad_cname;
173                 }
174         }
175
176         if ( value == NULL ) {
177                 return 0;
178         }
179
180         if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
181         {
182                 dncookie fdc = *dc;
183
184 #ifdef ENABLE_REWRITE
185                 fdc.ctx = "searchFilter";
186 #endif
187
188                 switch ( rwm_dn_massage( &fdc, value, &vtmp ) ) {
189                 case LDAP_SUCCESS:
190                         if ( vtmp.bv_val != value->bv_val ) {
191                                 freeval = 1;
192                         }
193                         break;
194                 
195                 case LDAP_UNWILLING_TO_PERFORM:
196                         return -1;
197
198                 case LDAP_OTHER:
199                         return -1;
200                 }
201
202         } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
203                 rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
204                 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
205                         vtmp = *value;
206                 }
207                 
208         } else {
209                 vtmp = *value;
210         }
211
212         filter_escape_value( &vtmp, mapped_value );
213
214         if ( freeval ) {
215                 ber_memfree( vtmp.bv_val );
216         }
217         
218         return 0;
219 }
220
221 int
222 rwm_filter_map_rewrite(
223                 dncookie                *dc,
224                 Filter                  *f,
225                 struct berval           *fstr,
226                 int                     remap )
227 {
228         int             i;
229         Filter          *p;
230         struct berval   atmp;
231         struct berval   vtmp;
232         ber_len_t       len;
233
234         if ( f == NULL ) {
235                 ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
236                 return -1;
237         }
238
239         switch ( f->f_choice ) {
240         case LDAP_FILTER_EQUALITY:
241                 if ( map_attr_value( dc, f->f_av_desc, &atmp,
242                                         &f->f_av_value, &vtmp, remap ) )
243                 {
244                         return -1;
245                 }
246
247                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
248                         + ( sizeof("(=)") - 1 );
249                 fstr->bv_val = malloc( fstr->bv_len + 1 );
250
251                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
252                         atmp.bv_val, vtmp.bv_val );
253
254                 ber_memfree( vtmp.bv_val );
255                 break;
256
257         case LDAP_FILTER_GE:
258                 if ( map_attr_value( dc, f->f_av_desc, &atmp,
259                                         &f->f_av_value, &vtmp, remap ) )
260                 {
261                         return -1;
262                 }
263
264                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
265                         + ( sizeof("(>=)") - 1 );
266                 fstr->bv_val = malloc( fstr->bv_len + 1 );
267
268                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
269                         atmp.bv_val, vtmp.bv_val );
270
271                 ber_memfree( vtmp.bv_val );
272                 break;
273
274         case LDAP_FILTER_LE:
275                 if ( map_attr_value( dc, f->f_av_desc, &atmp,
276                                         &f->f_av_value, &vtmp, remap ) )
277                 {
278                         return -1;
279                 }
280
281                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
282                         + ( sizeof("(<=)") - 1 );
283                 fstr->bv_val = malloc( fstr->bv_len + 1 );
284
285                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
286                         atmp.bv_val, vtmp.bv_val );
287
288                 ber_memfree( vtmp.bv_val );
289                 break;
290
291         case LDAP_FILTER_APPROX:
292                 if ( map_attr_value( dc, f->f_av_desc, &atmp,
293                                         &f->f_av_value, &vtmp, remap ) )
294                 {
295                         return -1;
296                 }
297
298                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
299                         + ( sizeof("(~=)") - 1 );
300                 fstr->bv_val = malloc( fstr->bv_len + 1 );
301
302                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
303                         atmp.bv_val, vtmp.bv_val );
304
305                 ber_memfree( vtmp.bv_val );
306                 break;
307
308         case LDAP_FILTER_SUBSTRINGS:
309                 if ( map_attr_value( dc, f->f_sub_desc, &atmp,
310                                         NULL, NULL, remap ) )
311                 {
312                         return -1;
313                 }
314
315                 /* cannot be a DN ... */
316
317                 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
318                 fstr->bv_val = malloc( fstr->bv_len + 128 );
319
320                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
321                         atmp.bv_val );
322
323                 if ( f->f_sub_initial.bv_val != NULL ) {
324                         len = fstr->bv_len;
325
326                         filter_escape_value( &f->f_sub_initial, &vtmp );
327
328                         fstr->bv_len += vtmp.bv_len;
329                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
330
331                         snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
332                                 /* "(attr=" */ "%s*)",
333                                 vtmp.bv_val );
334
335                         ber_memfree( vtmp.bv_val );
336                 }
337
338                 if ( f->f_sub_any != NULL ) {
339                         for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
340                                 len = fstr->bv_len;
341                                 filter_escape_value( &f->f_sub_any[i], &vtmp );
342
343                                 fstr->bv_len += vtmp.bv_len + 1;
344                                 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
345
346                                 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
347                                         /* "(attr=[init]*[any*]" */ "%s*)",
348                                         vtmp.bv_val );
349                                 ber_memfree( vtmp.bv_val );
350                         }
351                 }
352
353                 if ( f->f_sub_final.bv_val != NULL ) {
354                         len = fstr->bv_len;
355
356                         filter_escape_value( &f->f_sub_final, &vtmp );
357
358                         fstr->bv_len += vtmp.bv_len;
359                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
360
361                         snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
362                                 /* "(attr=[init*][any*]" */ "%s)",
363                                 vtmp.bv_val );
364
365                         ber_memfree( vtmp.bv_val );
366                 }
367
368                 break;
369
370         case LDAP_FILTER_PRESENT:
371                 if ( map_attr_value( dc, f->f_desc, &atmp,
372                                         NULL, NULL, remap ) )
373                 {
374                         return -1;
375                 }
376
377                 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
378                 fstr->bv_val = malloc( fstr->bv_len + 1 );
379
380                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
381                         atmp.bv_val );
382                 break;
383
384         case LDAP_FILTER_AND:
385         case LDAP_FILTER_OR:
386         case LDAP_FILTER_NOT:
387                 fstr->bv_len = sizeof("(%)") - 1;
388                 fstr->bv_val = malloc( fstr->bv_len + 128 );
389
390                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
391                         f->f_choice == LDAP_FILTER_AND ? '&' :
392                         f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
393
394                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
395                         len = fstr->bv_len;
396
397                         if ( rwm_filter_map_rewrite( dc, p, &vtmp, remap ) )
398                         {
399                                 return -1;
400                         }
401                         
402                         fstr->bv_len += vtmp.bv_len;
403                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
404
405                         snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
406                                 /*"("*/ "%s)", vtmp.bv_val );
407
408                         ch_free( vtmp.bv_val );
409                 }
410
411                 break;
412
413         case LDAP_FILTER_EXT: {
414                 if ( f->f_mr_desc ) {
415                         if ( map_attr_value( dc, f->f_mr_desc, &atmp,
416                                                 &f->f_mr_value, &vtmp, remap ) )
417                         {
418                                 return -1;
419                         }
420
421                 } else {
422                         atmp.bv_len = 0;
423                         atmp.bv_val = "";
424                         
425                         filter_escape_value( &f->f_mr_value, &vtmp );
426                 }
427                         
428
429                 fstr->bv_len = atmp.bv_len +
430                         ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
431                         ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
432                         vtmp.bv_len + ( sizeof("(:=)") - 1 );
433                 fstr->bv_val = malloc( fstr->bv_len + 1 );
434
435                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
436                         atmp.bv_val,
437                         f->f_mr_dnattrs ? ":dn" : "",
438                         f->f_mr_rule_text.bv_len ? ":" : "",
439                         f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
440                         vtmp.bv_val );
441                 ber_memfree( vtmp.bv_val );
442                 } break;
443
444         case SLAPD_FILTER_COMPUTED:
445                 ber_str2bv(
446                         f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
447                         f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
448                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
449                         "(?=error)",
450                         f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
451                         f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
452                         f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
453                         sizeof("(?=error)")-1,
454                         1, fstr );
455                 break;
456
457         default:
458                 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
459                 break;
460         }
461
462         return 0;
463 }
464
465 /*
466  * I don't like this much, but we need two different
467  * functions because different heap managers may be
468  * in use in back-ldap/meta to reduce the amount of
469  * calls to malloc routines, and some of the free()
470  * routines may be macros with args
471  */
472 int
473 ldap_dnattr_rewrite(
474         dncookie                *dc,
475         BerVarray               a_vals
476 )
477 {
478         struct berval   bv;
479         int             i, last;
480
481         for ( last = 0; a_vals[last].bv_val != NULL; last++ );
482         last--;
483
484         for ( i = 0; a_vals[i].bv_val != NULL; i++ ) {
485                 switch ( rwm_dn_massage( dc, &a_vals[i], &bv ) ) {
486                 case LDAP_UNWILLING_TO_PERFORM:
487                         /*
488                          * FIXME: need to check if it may be considered 
489                          * legal to trim values when adding/modifying;
490                          * it should be when searching (e.g. ACLs).
491                          */
492                         ch_free( a_vals[i].bv_val );
493                         if (last > i ) {
494                                 a_vals[i] = a_vals[last];
495                         }
496                         a_vals[last].bv_len = 0;
497                         a_vals[last].bv_val = NULL;
498                         last--;
499                         break;
500
501                 default:
502                         /* leave attr untouched if massage failed */
503                         if ( bv.bv_val && bv.bv_val != a_vals[i].bv_val ) {
504                                 ch_free( a_vals[i].bv_val );
505                                 a_vals[i] = bv;
506                         }
507                         break;
508                 }
509         }
510         
511         return 0;
512 }
513
514 int
515 ldap_dnattr_result_rewrite(
516         dncookie                *dc,
517         BerVarray               a_vals
518 )
519 {
520         struct berval   bv;
521         int             i, last;
522
523         for ( last = 0; a_vals[last].bv_val; last++ );
524         last--;
525
526         for ( i = 0; a_vals[i].bv_val; i++ ) {
527                 switch ( rwm_dn_massage( dc, &a_vals[i], &bv ) ) {
528                 case LDAP_UNWILLING_TO_PERFORM:
529                         /*
530                          * FIXME: need to check if it may be considered 
531                          * legal to trim values when adding/modifying;
532                          * it should be when searching (e.g. ACLs).
533                          */
534                         LBER_FREE( &a_vals[i].bv_val );
535                         if ( last > i ) {
536                                 a_vals[i] = a_vals[last];
537                         }
538                         a_vals[last].bv_val = NULL;
539                         a_vals[last].bv_len = 0;
540                         last--;
541                         break;
542
543                 default:
544                         /* leave attr untouched if massage failed */
545                         if ( bv.bv_val && a_vals[i].bv_val != bv.bv_val ) {
546                                 LBER_FREE( a_vals[i].bv_val );
547                                 a_vals[i] = bv;
548                         }
549                         break;
550                 }
551         }
552
553         return 0;
554 }
555
556 void
557 mapping_free( void *v_mapping )
558 {
559         struct ldapmapping *mapping = v_mapping;
560         ch_free( mapping->src.bv_val );
561         ch_free( mapping->dst.bv_val );
562         ch_free( mapping );
563 }
564
565 #endif /* SLAPD_OVER_RWM */