]> git.sur5r.net Git - openldap/blob - servers/slapd/overlays/rwmmap.c
5ecb959f1d827606646bbab46131ffbb5a02e655
[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-2004 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 rwm_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->m_src.bv_len - map2->m_src.bv_len;
45         if ( rc ) {
46                 return rc;
47         }
48         return strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val );
49 }
50
51 int
52 rwm_mapping_dup( void *c1, void *c2 )
53 {
54         struct ldapmapping *map1 = (struct ldapmapping *)c1;
55         struct ldapmapping *map2 = (struct ldapmapping *)c2;
56         int rc = map1->m_src.bv_len - map2->m_src.bv_len;
57
58         if ( rc ) {
59                 return 0;
60         }
61
62         return ( ( strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val ) == 0 ) ? -1 : 0 );
63 }
64
65 void
66 rwm_map_init( struct ldapmap *lm, struct ldapmapping **m )
67 {
68         struct ldapmapping *mapping;
69
70         assert( m );
71
72         *m = NULL;
73         
74         mapping = (struct ldapmapping *)ch_calloc( 2, 
75                         sizeof( struct ldapmapping ) );
76         if ( mapping == NULL ) {
77                 return;
78         }
79
80         ber_str2bv( "objectClass", sizeof("objectClass") - 1, 1,
81                         &mapping->m_src);
82         ber_dupbv( &mapping->m_dst, &mapping->m_src );
83         mapping[1].m_src = mapping->m_src;
84         mapping[1].m_dst = mapping->m_dst;
85
86         avl_insert( &lm->map, (caddr_t)mapping, 
87                         rwm_mapping_cmp, rwm_mapping_dup );
88         avl_insert( &lm->remap, (caddr_t)&mapping[1], 
89                         rwm_mapping_cmp, rwm_mapping_dup );
90         *m = mapping;
91 }
92
93 void
94 rwm_map( struct ldapmap *map, struct berval *s, struct berval *bv, int remap )
95 {
96         Avlnode *tree;
97         struct ldapmapping *mapping, fmapping;
98
99         if (remap == RWM_REMAP) {
100                 tree = map->remap;
101         } else {
102                 tree = map->map;
103         }
104
105         bv->bv_len = 0;
106         bv->bv_val = NULL;
107         fmapping.m_src = *s;
108         mapping = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping,
109                         rwm_mapping_cmp );
110         if ( mapping != NULL ) {
111                 if ( mapping->m_dst.bv_val ) {
112                         *bv = mapping->m_dst;
113                 }
114                 return;
115         }
116
117         if ( !map->drop_missing ) {
118                 *bv = *s;
119         }
120
121         return;
122 }
123
124 int
125 rwm_map_attrs(
126                 struct ldapmap *at_map,
127                 AttributeName *an,
128                 int remap,
129                 char ***mapped_attrs
130 )
131 {
132         int i, j;
133         char **na;
134         struct berval mapped;
135
136         if ( an == NULL ) {
137                 *mapped_attrs = NULL;
138                 return LDAP_SUCCESS;
139         }
140
141         for ( i = 0; an[i].an_name.bv_val; i++ ) {
142                 /*  */
143         }
144
145         na = (char **)ch_calloc( i + 1, sizeof( char * ) );
146         if (na == NULL) {
147                 *mapped_attrs = NULL;
148                 return LDAP_NO_MEMORY;
149         }
150
151         for ( i = j = 0; an[i].an_name.bv_val; i++ ) {
152                 rwm_map( at_map, &an[i].an_name, &mapped, remap );
153                 if ( mapped.bv_val != NULL && mapped.bv_val != '\0' ) {
154                         na[j++] = mapped.bv_val;
155                 }
156         }
157         if ( j == 0 && i != 0 ) {
158                 na[j++] = LDAP_NO_ATTRS;
159         }
160         na[j] = NULL;
161
162         *mapped_attrs = na;
163         return LDAP_SUCCESS;
164 }
165
166 static int
167 map_attr_value(
168                 dncookie                *dc,
169                 AttributeDescription    *ad,
170                 struct berval           *mapped_attr,
171                 struct berval           *value,
172                 struct berval           *mapped_value,
173                 int                     remap )
174 {
175         struct berval           vtmp;
176         int                     freeval = 0;
177
178         rwm_map( &dc->rwmap->rwm_at, &ad->ad_cname, mapped_attr, remap );
179         if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
180                 /*
181                  * FIXME: are we sure we need to search oc_map if at_map fails?
182                  */
183                 rwm_map( &dc->rwmap->rwm_oc, &ad->ad_cname, mapped_attr,
184                                 remap );
185                 if ( mapped_attr->bv_val == NULL
186                                 || mapped_attr->bv_val[0] == '\0' )
187                 {
188                         *mapped_attr = ad->ad_cname;
189                 }
190         }
191
192         if ( value == NULL ) {
193                 return 0;
194         }
195
196         if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
197         {
198                 dncookie fdc = *dc;
199
200 #ifdef ENABLE_REWRITE
201                 fdc.ctx = "searchFilter";
202 #endif
203
204                 switch ( rwm_dn_massage( &fdc, value, &vtmp ) ) {
205                 case LDAP_SUCCESS:
206                         if ( vtmp.bv_val != value->bv_val ) {
207                                 freeval = 1;
208                         }
209                         break;
210                 
211                 case LDAP_UNWILLING_TO_PERFORM:
212                         return -1;
213
214                 case LDAP_OTHER:
215                         return -1;
216                 }
217
218         } else if ( ad == slap_schema.si_ad_objectClass
219                         || ad == slap_schema.si_ad_structuralObjectClass )
220         {
221                 rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
222                 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
223                         vtmp = *value;
224                 }
225                 
226         } else {
227                 vtmp = *value;
228         }
229
230         filter_escape_value( &vtmp, mapped_value );
231
232         if ( freeval ) {
233                 ber_memfree( vtmp.bv_val );
234         }
235         
236         return 0;
237 }
238
239 int
240 rwm_filter_map_rewrite(
241                 dncookie                *dc,
242                 Filter                  *f,
243                 struct berval           *fstr,
244                 int                     remap )
245 {
246         int             i;
247         Filter          *p;
248         struct berval   atmp,
249                         vtmp,
250                         tmp;
251         static struct berval
252                         ber_bvfalse = BER_BVC( "(?=false)" ),
253                         ber_bvtrue = BER_BVC( "(?=true)" ),
254                         ber_bvundefined = BER_BVC( "(?=undefined)" ),
255                         ber_bverror = BER_BVC( "(?=error)" ),
256                         ber_bvunknown = BER_BVC( "(?=unknown)" ),
257                         ber_bvnone = BER_BVC( "(?=none)" );
258         ber_len_t       len;
259
260         if ( f == NULL ) {
261                 ber_dupbv( fstr, &ber_bvnone );
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                 switch ( f->f_result ) {
472                 case LDAP_COMPARE_FALSE:
473                         tmp = ber_bvfalse;
474                         break;
475
476                 case LDAP_COMPARE_TRUE:
477                         tmp = ber_bvtrue;
478                         break;
479                         
480                 case SLAPD_COMPARE_UNDEFINED:
481                         tmp = ber_bvundefined;
482                         break;
483                         
484                 default:
485                         tmp = ber_bverror;
486                         break;
487                 }
488
489                 ber_dupbv( fstr, &tmp );
490                 break;
491                 
492         default:
493                 ber_dupbv( fstr, &ber_bvunknown );
494                 break;
495         }
496
497         return 0;
498 }
499
500 /*
501  * I don't like this much, but we need two different
502  * functions because different heap managers may be
503  * in use in back-ldap/meta to reduce the amount of
504  * calls to malloc routines, and some of the free()
505  * routines may be macros with args
506  */
507 int
508 rwm_dnattr_rewrite(
509         Operation               *op,
510         SlapReply               *rs,
511         void                    *cookie,
512         BerVarray               a_vals
513         )
514 {
515         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
516         struct ldaprwmap        *rwmap = 
517                         (struct ldaprwmap *)on->on_bi.bi_private;
518
519         struct berval           bv;
520         int                     i, last;
521
522         dncookie                dc;
523
524         /*
525          * Rewrite the bind dn if needed
526          */
527         dc.rwmap = rwmap;
528 #ifdef ENABLE_REWRITE
529         dc.conn = op->o_conn;
530         dc.rs = rs;
531         dc.ctx = (char *)cookie;
532 #else
533         dc.tofrom = ((int *)cookie)[0];
534         dc.normalized = 0;
535 #endif
536
537         for ( last = 0; a_vals[last].bv_val != NULL; last++ );
538         last--;
539
540         for ( i = 0; a_vals[i].bv_val != NULL; i++ ) {
541                 switch ( rwm_dn_massage( &dc, &a_vals[i], &bv ) ) {
542                 case LDAP_UNWILLING_TO_PERFORM:
543                         /*
544                          * FIXME: need to check if it may be considered 
545                          * legal to trim values when adding/modifying;
546                          * it should be when searching (e.g. ACLs).
547                          */
548                         ch_free( a_vals[i].bv_val );
549                         if (last > i ) {
550                                 a_vals[i] = a_vals[last];
551                         }
552                         a_vals[last].bv_len = 0;
553                         a_vals[last].bv_val = NULL;
554                         last--;
555                         break;
556
557                 default:
558                         /* leave attr untouched if massage failed */
559                         if ( bv.bv_val && bv.bv_val != a_vals[i].bv_val ) {
560                                 ch_free( a_vals[i].bv_val );
561                                 a_vals[i] = bv;
562                         }
563                         break;
564                 }
565         }
566         
567         return 0;
568 }
569
570 int
571 rwm_dnattr_result_rewrite(
572         dncookie                *dc,
573         BerVarray               a_vals
574 )
575 {
576         struct berval   bv;
577         int             i, last;
578
579         for ( last = 0; a_vals[last].bv_val; last++ );
580         last--;
581
582         for ( i = 0; a_vals[i].bv_val; i++ ) {
583                 switch ( rwm_dn_massage( dc, &a_vals[i], &bv ) ) {
584                 case LDAP_UNWILLING_TO_PERFORM:
585                         /*
586                          * FIXME: need to check if it may be considered 
587                          * legal to trim values when adding/modifying;
588                          * it should be when searching (e.g. ACLs).
589                          */
590                         LBER_FREE( &a_vals[i].bv_val );
591                         if ( last > i ) {
592                                 a_vals[i] = a_vals[last];
593                         }
594                         a_vals[last].bv_val = NULL;
595                         a_vals[last].bv_len = 0;
596                         last--;
597                         break;
598
599                 default:
600                         /* leave attr untouched if massage failed */
601                         if ( bv.bv_val && a_vals[i].bv_val != bv.bv_val ) {
602                                 LBER_FREE( a_vals[i].bv_val );
603                                 a_vals[i] = bv;
604                         }
605                         break;
606                 }
607         }
608
609         return 0;
610 }
611
612 void
613 rwm_mapping_free( void *v_mapping )
614 {
615         struct ldapmapping *mapping = v_mapping;
616
617         if ( mapping[0].m_src.bv_val ) {
618                 ch_free( mapping[0].m_src.bv_val );
619         }
620
621         if ( mapping[0].m_flags & RWMMAP_F_FREE_SRC ) {
622                 if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
623                         if ( mapping[0].m_src_oc ) {
624                                 ch_free( mapping[0].m_src_oc );
625                         }
626
627                 } else {
628                         if ( mapping[0].m_src_ad ) {
629                                 ch_free( mapping[0].m_src_ad );
630                         }
631                 }
632         }
633
634         if ( mapping[0].m_dst.bv_val ) {
635                 ch_free( mapping[0].m_dst.bv_val );
636         }
637
638         if ( mapping[0].m_flags & RWMMAP_F_FREE_DST ) {
639                 if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
640                         if ( mapping[0].m_dst_oc ) {
641                                 ch_free( mapping[0].m_dst_oc );
642                         }
643
644                 } else {
645                         if ( mapping[0].m_dst_ad ) {
646                                 ch_free( mapping[0].m_dst_ad );
647                         }
648                 }
649         }
650
651         ch_free( mapping );
652
653 }
654
655 #endif /* SLAPD_OVER_RWM */