]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/map.c
Fix prev commit
[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 LDAP_SUCCESS;
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 = "searchFilterAttrDN";
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                 case LDAP_OTHER:
195                         return LDAP_OTHER;
196                 }
197
198         } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
199                 ldap_back_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
200                 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
201                         vtmp = *value;
202                 }
203                 
204         } else {
205                 vtmp = *value;
206         }
207
208         filter_escape_value( &vtmp, mapped_value );
209
210         if ( freeval ) {
211                 ber_memfree( vtmp.bv_val );
212         }
213         
214         return LDAP_SUCCESS;
215 }
216
217 static int
218 ldap_int_back_filter_map_rewrite(
219                 dncookie                *dc,
220                 Filter                  *f,
221                 struct berval           *fstr,
222                 int                     remap )
223 {
224         int             i, rc;
225         Filter          *p;
226         struct berval   atmp;
227         struct berval   vtmp;
228         ber_len_t       len;
229
230         if ( f == NULL ) {
231                 ber_str2bv( "(?=error)", sizeof("(?=error)")-1, 1, fstr );
232                 return LDAP_OTHER;
233         }
234
235         switch ( f->f_choice ) {
236         case LDAP_FILTER_EQUALITY:
237                 rc = map_attr_value( dc, f->f_av_desc, &atmp,
238                                         &f->f_av_value, &vtmp, remap );
239                 if ( rc ) {
240                         return rc;
241                 }
242
243                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
244                         + ( sizeof("(=)") - 1 );
245                 fstr->bv_val = malloc( fstr->bv_len + 1 );
246
247                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
248                         atmp.bv_val, vtmp.bv_val );
249
250                 ber_memfree( vtmp.bv_val );
251                 break;
252
253         case LDAP_FILTER_GE:
254                 rc = map_attr_value( dc, f->f_av_desc, &atmp,
255                                         &f->f_av_value, &vtmp, remap );
256                 if ( rc ) {
257                         return rc;
258                 }
259
260                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
261                         + ( sizeof("(>=)") - 1 );
262                 fstr->bv_val = malloc( fstr->bv_len + 1 );
263
264                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
265                         atmp.bv_val, vtmp.bv_val );
266
267                 ber_memfree( vtmp.bv_val );
268                 break;
269
270         case LDAP_FILTER_LE:
271                 rc = map_attr_value( dc, f->f_av_desc, &atmp,
272                                         &f->f_av_value, &vtmp, remap );
273                 if ( rc ) {
274                         return rc;
275                 }
276
277                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
278                         + ( sizeof("(<=)") - 1 );
279                 fstr->bv_val = malloc( fstr->bv_len + 1 );
280
281                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
282                         atmp.bv_val, vtmp.bv_val );
283
284                 ber_memfree( vtmp.bv_val );
285                 break;
286
287         case LDAP_FILTER_APPROX:
288                 rc = map_attr_value( dc, f->f_av_desc, &atmp,
289                                         &f->f_av_value, &vtmp, remap );
290                 if ( rc ) {
291                         return rc;
292                 }
293
294                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
295                         + ( sizeof("(~=)") - 1 );
296                 fstr->bv_val = malloc( fstr->bv_len + 1 );
297
298                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
299                         atmp.bv_val, vtmp.bv_val );
300
301                 ber_memfree( vtmp.bv_val );
302                 break;
303
304         case LDAP_FILTER_SUBSTRINGS:
305                 rc = map_attr_value( dc, f->f_sub_desc, &atmp,
306                                         NULL, NULL, remap );
307                 if ( rc ) {
308                         return rc;
309                 }
310
311                 /* cannot be a DN ... */
312
313                 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
314                 fstr->bv_val = malloc( fstr->bv_len + 128 );
315
316                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
317                         atmp.bv_val );
318
319                 if ( f->f_sub_initial.bv_val != NULL ) {
320                         len = fstr->bv_len;
321
322                         filter_escape_value( &f->f_sub_initial, &vtmp );
323
324                         fstr->bv_len += vtmp.bv_len;
325                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
326
327                         snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
328                                 /* "(attr=" */ "%s*)",
329                                 vtmp.bv_val );
330
331                         ber_memfree( vtmp.bv_val );
332                 }
333
334                 if ( f->f_sub_any != NULL ) {
335                         for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
336                                 len = fstr->bv_len;
337                                 filter_escape_value( &f->f_sub_any[i], &vtmp );
338
339                                 fstr->bv_len += vtmp.bv_len + 1;
340                                 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
341
342                                 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
343                                         /* "(attr=[init]*[any*]" */ "%s*)",
344                                         vtmp.bv_val );
345                                 ber_memfree( vtmp.bv_val );
346                         }
347                 }
348
349                 if ( f->f_sub_final.bv_val != NULL ) {
350                         len = fstr->bv_len;
351
352                         filter_escape_value( &f->f_sub_final, &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 - 1], vtmp.bv_len + 3,
358                                 /* "(attr=[init*][any*]" */ "%s)",
359                                 vtmp.bv_val );
360
361                         ber_memfree( vtmp.bv_val );
362                 }
363
364                 break;
365
366         case LDAP_FILTER_PRESENT:
367                 rc = map_attr_value( dc, f->f_desc, &atmp,
368                                         NULL, NULL, remap );
369                 if ( rc ) {
370                         return rc;
371                 }
372
373                 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
374                 fstr->bv_val = malloc( fstr->bv_len + 1 );
375
376                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
377                         atmp.bv_val );
378                 break;
379
380         case LDAP_FILTER_AND:
381         case LDAP_FILTER_OR:
382         case LDAP_FILTER_NOT:
383                 fstr->bv_len = sizeof("(%)") - 1;
384                 fstr->bv_val = malloc( fstr->bv_len + 128 );
385
386                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
387                         f->f_choice == LDAP_FILTER_AND ? '&' :
388                         f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
389
390                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
391                         len = fstr->bv_len;
392
393                         rc = ldap_int_back_filter_map_rewrite( dc, p, &vtmp, remap );
394                         if ( rc != LDAP_SUCCESS ) {
395                                 return rc;
396                         }
397                         
398                         fstr->bv_len += vtmp.bv_len;
399                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
400
401                         snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
402                                 /*"("*/ "%s)", vtmp.bv_val );
403
404                         ch_free( vtmp.bv_val );
405                 }
406
407                 break;
408
409         case LDAP_FILTER_EXT: {
410                 if ( f->f_mr_desc ) {
411                         rc = map_attr_value( dc, f->f_mr_desc, &atmp,
412                                                 &f->f_mr_value, &vtmp, remap );
413                         if ( rc ) {
414                                 return rc;
415                         }
416
417                 } else {
418                         atmp.bv_len = 0;
419                         atmp.bv_val = "";
420                         
421                         filter_escape_value( &f->f_mr_value, &vtmp );
422                 }
423                         
424
425                 fstr->bv_len = atmp.bv_len +
426                         ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
427                         ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
428                         vtmp.bv_len + ( sizeof("(:=)") - 1 );
429                 fstr->bv_val = malloc( fstr->bv_len + 1 );
430
431                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
432                         atmp.bv_val,
433                         f->f_mr_dnattrs ? ":dn" : "",
434                         f->f_mr_rule_text.bv_len ? ":" : "",
435                         f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
436                         vtmp.bv_val );
437                 ber_memfree( vtmp.bv_val );
438                 } break;
439
440         case SLAPD_FILTER_COMPUTED:
441                 ber_str2bv(
442                         f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
443                         f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
444                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
445                         "(?=error)",
446                         f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
447                         f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
448                         f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
449                         sizeof("(?=error)")-1,
450                         1, fstr );
451                 return LDAP_COMPARE_FALSE;
452
453         default:
454                 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
455                 return LDAP_COMPARE_FALSE;
456         }
457
458         return LDAP_SUCCESS;
459 }
460
461 int
462 ldap_back_filter_map_rewrite(
463                 dncookie                *dc,
464                 Filter                  *f,
465                 struct berval           *fstr,
466                 int                     remap )
467 {
468         int             rc;
469         dncookie        fdc;
470         struct berval   ftmp;
471
472         rc = ldap_int_back_filter_map_rewrite( dc, f, fstr, remap );
473
474 #ifdef ENABLE_REWRITE
475         if ( rc != LDAP_SUCCESS ) {
476                 return rc;
477         }
478
479         fdc = *dc;
480         ftmp = *fstr;
481
482         fdc.ctx = "searchFilter";
483
484         switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx, 
485                                 ( ftmp.bv_len ? ftmp.bv_val : "" ), 
486                                 fdc.conn, &fstr->bv_val )) {
487         case REWRITE_REGEXEC_OK:
488                 if ( fstr->bv_val != NULL ) {
489                         fstr->bv_len = strlen( fstr->bv_val );
490                         free( ftmp.bv_val );
491                 } else {
492                         *fstr = ftmp;
493                 }
494
495 #ifdef NEW_LOGGING
496                 LDAP_LOG( BACK_LDAP, DETAIL1, 
497                         "[rw] %s: \"%s\" -> \"%s\"\n",
498                         dc->ctx, ftmp.bv_val, fstr->bv_val );           
499 #else /* !NEW_LOGGING */
500                 Debug( LDAP_DEBUG_ARGS,
501                         "[rw] %s: \"%s\" -> \"%s\"\n",
502                         dc->ctx, ftmp.bv_val, fstr->bv_val );           
503 #endif /* !NEW_LOGGING */
504                 rc = LDAP_SUCCESS;
505                 break;
506                 
507         case REWRITE_REGEXEC_UNWILLING:
508                 if ( fdc.rs ) {
509                         fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
510                         fdc.rs->sr_text = "Operation not allowed";
511                 }
512                 rc = LDAP_UNWILLING_TO_PERFORM;
513                 break;
514                 
515         case REWRITE_REGEXEC_ERR:
516                 if ( fdc.rs ) {
517                         fdc.rs->sr_err = LDAP_OTHER;
518                         fdc.rs->sr_text = "Rewrite error";
519                 }
520                 rc = LDAP_OTHER;
521                 break;
522         }
523
524 #endif /* ENABLE_REWRITE */
525         return rc;
526 }
527
528 /*
529  * I don't like this much, but we need two different
530  * functions because different heap managers may be
531  * in use in back-ldap/meta to reduce the amount of
532  * calls to malloc routines, and some of the free()
533  * routines may be macros with args
534  */
535 int
536 ldap_dnattr_rewrite(
537         dncookie                *dc,
538         BerVarray               a_vals
539 )
540 {
541         struct berval   bv;
542         int             i, last;
543
544         for ( last = 0; a_vals[last].bv_val != NULL; last++ );
545         last--;
546
547         for ( i = 0; a_vals[i].bv_val != NULL; i++ ) {
548                 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
549                 case LDAP_UNWILLING_TO_PERFORM:
550                         /*
551                          * FIXME: need to check if it may be considered 
552                          * legal to trim values when adding/modifying;
553                          * it should be when searching (e.g. ACLs).
554                          */
555                         ch_free( a_vals[i].bv_val );
556                         if (last > i ) {
557                                 a_vals[i] = a_vals[last];
558                         }
559                         a_vals[last].bv_len = 0;
560                         a_vals[last].bv_val = NULL;
561                         last--;
562                         break;
563
564                 default:
565                         /* leave attr untouched if massage failed */
566                         if ( bv.bv_val && bv.bv_val != a_vals[i].bv_val ) {
567                                 ch_free( a_vals[i].bv_val );
568                                 a_vals[i] = bv;
569                         }
570                         break;
571                 }
572         }
573         
574         return 0;
575 }
576
577 int
578 ldap_dnattr_result_rewrite(
579         dncookie                *dc,
580         BerVarray               a_vals
581 )
582 {
583         struct berval   bv;
584         int             i, last;
585
586         for ( last = 0; a_vals[last].bv_val; last++ );
587         last--;
588
589         for ( i = 0; a_vals[i].bv_val; i++ ) {
590                 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
591                 case LDAP_UNWILLING_TO_PERFORM:
592                         /*
593                          * FIXME: need to check if it may be considered 
594                          * legal to trim values when adding/modifying;
595                          * it should be when searching (e.g. ACLs).
596                          */
597                         LBER_FREE( &a_vals[i].bv_val );
598                         if ( last > i ) {
599                                 a_vals[i] = a_vals[last];
600                         }
601                         a_vals[last].bv_val = NULL;
602                         a_vals[last].bv_len = 0;
603                         last--;
604                         break;
605
606                 default:
607                         /* leave attr untouched if massage failed */
608                         if ( bv.bv_val && a_vals[i].bv_val != bv.bv_val ) {
609                                 LBER_FREE( a_vals[i].bv_val );
610                                 a_vals[i] = bv;
611                         }
612                         break;
613                 }
614         }
615
616         return 0;
617 }
618