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