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