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