]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/map.c
map attrs improvement
[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 int
48 mapping_cmp ( const void *c1, const void *c2 )
49 {
50         struct ldapmapping *map1 = (struct ldapmapping *)c1;
51         struct ldapmapping *map2 = (struct ldapmapping *)c2;
52         int rc = map1->src.bv_len - map2->src.bv_len;
53         if (rc) return rc;
54         return ( strcasecmp(map1->src.bv_val, map2->src.bv_val) );
55 }
56
57 int
58 mapping_dup ( void *c1, void *c2 )
59 {
60         struct ldapmapping *map1 = (struct ldapmapping *)c1;
61         struct ldapmapping *map2 = (struct ldapmapping *)c2;
62
63         return( ( strcasecmp(map1->src.bv_val, map2->src.bv_val) == 0 ) ? -1 : 0 );
64 }
65
66 void
67 ldap_back_map_init ( struct ldapmap *lm, struct ldapmapping **m )
68 {
69         struct ldapmapping *mapping;
70
71         assert( m );
72
73         *m = NULL;
74         
75         mapping = (struct ldapmapping *)ch_calloc( 2, 
76                         sizeof( struct ldapmapping ) );
77         if ( mapping == NULL ) {
78                 return;
79         }
80
81         ber_str2bv( "objectclass", sizeof("objectclass")-1, 1, &mapping->src);
82         ber_dupbv( &mapping->dst, &mapping->src );
83         mapping[1].src = mapping->src;
84         mapping[1].dst = mapping->dst;
85
86         avl_insert( &lm->map, (caddr_t)mapping, 
87                         mapping_cmp, mapping_dup );
88         avl_insert( &lm->remap, (caddr_t)&mapping[1], 
89                         mapping_cmp, mapping_dup );
90         *m = mapping;
91 }
92
93 void
94 ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv,
95         int remap )
96 {
97         Avlnode *tree;
98         struct ldapmapping *mapping, fmapping;
99
100         if (remap == BACKLDAP_REMAP)
101                 tree = map->remap;
102         else
103                 tree = map->map;
104
105         bv->bv_len = 0;
106         bv->bv_val = NULL;
107         fmapping.src = *s;
108         mapping = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp );
109         if (mapping != NULL) {
110                 if ( mapping->dst.bv_val )
111                         *bv = mapping->dst;
112                 return;
113         }
114
115         if (!map->drop_missing)
116                 *bv = *s;
117
118         return;
119 }
120
121 char *
122 ldap_back_map_filter(
123                 struct ldapmap *at_map,
124                 struct ldapmap *oc_map,
125                 struct berval *f,
126                 int remap
127 )
128 {
129         char *nf, *p, *q, *s, c;
130         int len, extra, plen, in_quote;
131         struct berval m, tmp;
132
133         if (f == NULL)
134                 return(NULL);
135
136         len = f->bv_len;
137         extra = len;
138         len *= 2;
139         nf = ch_malloc( len + 1 );
140         if (nf == NULL)
141                 return(NULL);
142
143         /* this loop assumes the filter ends with one
144          * of the delimiter chars -- probably ')'.
145          */
146
147         s = nf;
148         q = NULL;
149         in_quote = 0;
150         for (p = f->bv_val; (c = *p); p++) {
151                 if (c == '"') {
152                         in_quote = !in_quote;
153                         if (q != NULL) {
154                                 plen = p - q;
155                                 AC_MEMCPY(s, q, plen);
156                                 s += plen;
157                                 q = NULL;
158                         }
159                         *s++ = c;
160                 } else if (in_quote) {
161                         /* ignore everything in quotes --
162                          * what about attrs in DNs?
163                          */
164                         *s++ = c;
165                 } else if (c != '(' && c != ')'
166                         && c != '=' && c != '>' && c != '<'
167                         && c != '|' && c != '&')
168                 {
169                         if (q == NULL)
170                                 q = p;
171                 } else {
172                         if (q != NULL) {
173                                 *p = 0;
174                                 tmp.bv_len = p - q;
175                                 tmp.bv_val = q;
176                                 ldap_back_map(at_map, &tmp, &m, remap);
177                                 if (m.bv_val == NULL || m.bv_val[0] == '\0') {
178                                         /*
179                                          * FIXME: are we sure we need to search 
180                                          * oc_map if at_map fails?
181                                          */
182                                         ldap_back_map(oc_map, &tmp, &m, remap);
183                                         if (m.bv_val == NULL || m.bv_val[0] == '\0') {
184                                                 m = tmp;
185                                         }
186                                 }
187                                 extra += p - q;
188                                 plen = m.bv_len;
189                                 extra -= plen;
190                                 if (extra < 0) {
191                                         char *tmpnf;
192                                         while (extra < 0) {
193                                                 extra += len;
194                                                 len *= 2;
195                                         }
196                                         s -= (long)nf;
197                                         tmpnf = ch_realloc(nf, len + 1);
198                                         if (tmpnf == NULL) {
199                                                 ch_free(nf);
200                                                 return(NULL);
201                                         }
202                                         nf = tmpnf;
203                                         s += (long)nf;
204                                 }
205                                 AC_MEMCPY(s, m.bv_val, plen);
206                                 s += plen;
207                                 *p = c;
208                                 q = NULL;
209                         }
210                         *s++ = c;
211                 }
212         }
213         *s = 0;
214         return(nf);
215 }
216
217 int
218 ldap_back_map_attrs(
219                 struct ldapmap *at_map,
220                 AttributeName *an,
221                 int remap,
222                 char ***mapped_attrs
223 )
224 {
225         int i, j;
226         char **na;
227         struct berval mapped;
228
229         if (an == NULL) {
230                 *mapped_attrs = NULL;
231                 return LDAP_SUCCESS;
232         }
233
234         for (i = 0; an[i].an_name.bv_val; i++) {
235                 /*  */
236         }
237
238         na = (char **)ch_calloc( i + 1, sizeof(char *) );
239         if (na == NULL) {
240                 *mapped_attrs = NULL;
241                 return LDAP_NO_MEMORY;
242         }
243
244         for (i = j = 0; an[i].an_name.bv_val; i++) {
245                 ldap_back_map(at_map, &an[i].an_name, &mapped, remap);
246                 if (mapped.bv_val != NULL && mapped.bv_val != '\0')
247                         na[j++] = mapped.bv_val;
248         }
249         if (j == 0 && i != 0)
250                 na[j++] = LDAP_NO_ATTRS;
251         na[j] = NULL;
252
253         *mapped_attrs = na;
254         return LDAP_SUCCESS;
255 }
256
257 #ifdef ENABLE_REWRITE
258
259 static int
260 map_attr_value_(
261                 struct rewrite_info     *info,
262                 void                    *cookie,
263                 struct ldapmap          *at_map,
264                 struct ldapmap          *oc_map,
265                 AttributeDescription    *ad,
266                 struct berval           *mapped_attr,
267                 struct berval           *value,
268                 struct berval           *mapped_value,
269                 int                     remap )
270 {
271         struct berval           vtmp;
272         int                     freeval = 0;
273
274         ldap_back_map( at_map, &ad->ad_cname, mapped_attr, remap );
275         if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
276                 /*
277                  * FIXME: are we sure we need to search oc_map if at_map fails?
278                  */
279                 ldap_back_map( oc_map, &ad->ad_cname, mapped_attr, remap );
280                 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
281                         *mapped_attr = ad->ad_cname;
282                 }
283         }
284
285         if ( value == NULL ) {
286                 return 0;
287         }
288
289         if ( strcmp( ad->ad_type->sat_syntax->ssyn_oid, SLAPD_DN_SYNTAX ) == 0 )
290         {
291                 switch ( rewrite_session( info, "searchFilter",
292                                         value->bv_val, cookie, &vtmp.bv_val ) ) {
293                 case REWRITE_REGEXEC_OK:
294                         if ( vtmp.bv_val == NULL ) {
295                                 vtmp = *value;
296                         } else {
297                                 vtmp.bv_len = strlen( vtmp.bv_val );
298                                 freeval = 1;
299                         }
300 #ifdef NEW_LOGGING
301                         LDAP_LOG( BACK_LDAP, DETAIL1, 
302                                 "[rw] searchFilter: \"%s\" -> \"%s\"\n", 
303                                 value->bv_val, vtmp.bv_val, 0 );
304 #else /* !NEW_LOGGING */
305                         Debug( LDAP_DEBUG_ARGS, "rw> searchFilter: \"%s\" -> \"%s\"\n%s",
306                                         value->bv_val, vtmp.bv_val, "" );
307 #endif /* !NEW_LOGGING */
308                         break;
309
310                 
311                 case REWRITE_REGEXEC_UNWILLING:
312                         return -1;
313
314                 case REWRITE_REGEXEC_ERR:
315                         return -1;
316                 }
317
318         } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
319                 ldap_back_map( oc_map, value, &vtmp, remap );
320                 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
321                         vtmp = *value;
322                 }
323                 
324         } else {
325                 vtmp = *value;
326         }
327
328         filter_escape_value( &vtmp, mapped_value );
329
330         if ( freeval ) {
331                 ber_memfree( vtmp.bv_val );
332         }
333         
334         return 0;
335 }
336
337 #define map_attr_value(at_map, oc_map, ad, mapped_attr, value, mapped_value, remap) \
338         map_attr_value_(info, cookie, (at_map), (oc_map), (ad), (mapped_attr), (value), (mapped_value), (remap))
339 #define ldap_back_filter_map_rewrite(at_map, oc_map, f, fstr, remap) \
340         ldap_back_filter_map_rewrite_(info, cookie, (at_map), (oc_map), (f), (fstr), (remap))
341
342 #else /* ! ENABLE_REWRITE */
343
344 static int
345 map_attr_value_(
346                 struct ldapmap          *at_map,
347                 struct ldapmap          *oc_map,
348                 AttributeDescription    *ad,
349                 struct berval           *mapped_attr,
350                 struct berval           *value,
351                 struct berval           *mapped_value,
352                 int                     remap )
353 {
354         struct berval           vtmp;
355
356         ldap_back_map( at_map, &ad->ad_cname, mapped_attr, remap );
357         if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
358                 /*
359                  * FIXME: are we sure we need to search oc_map if at_map fails?
360                  */
361                 ldap_back_map( oc_map, &ad->ad_cname, mapped_attr, remap );
362                 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
363                         *mapped_attr = ad->ad_cname;
364                 }
365         }
366
367         if ( value == NULL ) {
368                 return 0;
369         }
370
371         if ( strcmp( ad->ad_type->sat_syntax->ssyn_oid, SLAPD_DN_SYNTAX ) == 0 )
372         {
373                 /* FIXME: use suffix massage capabilities */
374                 vtmp = *value;
375
376         } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
377                 ldap_back_map( oc_map, value, &vtmp, remap );
378                 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
379                         vtmp = *value;
380                 }
381                 
382         } else {
383                 vtmp = *value;
384         }
385
386         filter_escape_value( &vtmp, mapped_value );
387
388         return 0;
389 }
390
391 #define map_attr_value(at_map, oc_map, ad, mapped_attr, value, mapped_value, remap) \
392         map_attr_value_((at_map), (oc_map), (ad), (mapped_attr), (value), (mapped_value), (remap))
393 #define ldap_back_filter_map_rewrite(at_map, oc_map, f, fstr, remap) \
394         ldap_back_filter_map_rewrite_((at_map), (oc_map), (f), (fstr), (remap))
395
396 #endif /* ! ENABLE_REWRITE */
397
398 int
399 ldap_back_filter_map_rewrite_(
400 #ifdef ENABLE_REWRITE
401                 struct rewrite_info     *info,
402                 void                    *cookie,
403 #endif /* ENABLE_REWRITE */
404                 struct ldapmap          *at_map,
405                 struct ldapmap          *oc_map,
406                 Filter                  *f,
407                 struct berval           *fstr,
408                 int                     remap )
409 {
410         int             i;
411         Filter          *p;
412         struct berval   atmp;
413         struct berval   vtmp;
414         ber_len_t       len;
415
416         if ( f == NULL ) {
417                 ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
418                 return -1;
419         }
420
421         switch ( f->f_choice ) {
422         case LDAP_FILTER_EQUALITY:
423                 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
424                                         &f->f_av_value, &vtmp, remap ) )
425                 {
426                         return -1;
427                 }
428
429                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
430                         + ( sizeof("(=)") - 1 );
431                 fstr->bv_val = malloc( fstr->bv_len + 1 );
432
433                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
434                         atmp.bv_val, vtmp.bv_val );
435
436                 ber_memfree( vtmp.bv_val );
437                 break;
438
439         case LDAP_FILTER_GE:
440                 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
441                                 &f->f_av_value, &vtmp, remap ) )
442                 {
443                         return -1;
444                 }
445
446                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
447                         + ( sizeof("(>=)") - 1 );
448                 fstr->bv_val = malloc( fstr->bv_len + 1 );
449
450                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
451                         atmp.bv_val, vtmp.bv_val );
452
453                 ber_memfree( vtmp.bv_val );
454                 break;
455
456         case LDAP_FILTER_LE:
457                 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
458                                         &f->f_av_value, &vtmp, remap ) )
459                 {
460                         return -1;
461                 }
462
463                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
464                         + ( sizeof("(<=)") - 1 );
465                 fstr->bv_val = malloc( fstr->bv_len + 1 );
466
467                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
468                         atmp.bv_val, vtmp.bv_val );
469
470                 ber_memfree( vtmp.bv_val );
471                 break;
472
473         case LDAP_FILTER_APPROX:
474                 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
475                                         &f->f_av_value, &vtmp, remap ) )
476                 {
477                         return -1;
478                 }
479
480                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
481                         + ( sizeof("(~=)") - 1 );
482                 fstr->bv_val = malloc( fstr->bv_len + 1 );
483
484                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
485                         atmp.bv_val, vtmp.bv_val );
486
487                 ber_memfree( vtmp.bv_val );
488                 break;
489
490         case LDAP_FILTER_SUBSTRINGS:
491                 if ( map_attr_value( at_map, oc_map, f->f_sub_desc, &atmp,
492                                         NULL, NULL, remap ) )
493                 {
494                         return -1;
495                 }
496
497                 /* cannot be a DN ... */
498
499                 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
500                 fstr->bv_val = malloc( fstr->bv_len + 128 );
501
502                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
503                         atmp.bv_val );
504
505                 if ( f->f_sub_initial.bv_val != NULL ) {
506                         len = fstr->bv_len;
507
508                         filter_escape_value( &f->f_sub_initial, &vtmp );
509
510                         fstr->bv_len += vtmp.bv_len;
511                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
512
513                         snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
514                                 /* "(attr=" */ "%s*)",
515                                 vtmp.bv_val );
516
517                         ber_memfree( vtmp.bv_val );
518                 }
519
520                 if ( f->f_sub_any != NULL ) {
521                         for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
522                                 len = fstr->bv_len;
523                                 filter_escape_value( &f->f_sub_any[i], &vtmp );
524
525                                 fstr->bv_len += vtmp.bv_len + 1;
526                                 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
527
528                                 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
529                                         /* "(attr=[init]*[any*]" */ "%s*)",
530                                         vtmp.bv_val );
531                                 ber_memfree( vtmp.bv_val );
532                         }
533                 }
534
535                 if ( f->f_sub_final.bv_val != NULL ) {
536                         len = fstr->bv_len;
537
538                         filter_escape_value( &f->f_sub_final, &vtmp );
539
540                         fstr->bv_len += vtmp.bv_len;
541                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
542
543                         snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
544                                 /* "(attr=[init*][any*]" */ "%s)",
545                                 vtmp.bv_val );
546
547                         ber_memfree( vtmp.bv_val );
548                 }
549
550                 break;
551
552         case LDAP_FILTER_PRESENT:
553                 if ( map_attr_value( at_map, oc_map, f->f_desc, &atmp,
554                                         NULL, NULL, remap ) )
555                 {
556                         return -1;
557                 }
558
559                 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
560                 fstr->bv_val = malloc( fstr->bv_len + 1 );
561
562                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
563                         atmp.bv_val );
564                 break;
565
566         case LDAP_FILTER_AND:
567         case LDAP_FILTER_OR:
568         case LDAP_FILTER_NOT:
569                 fstr->bv_len = sizeof("(%)") - 1;
570                 fstr->bv_val = malloc( fstr->bv_len + 128 );
571
572                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
573                         f->f_choice == LDAP_FILTER_AND ? '&' :
574                         f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
575
576                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
577                         len = fstr->bv_len;
578
579                         if ( ldap_back_filter_map_rewrite( at_map, oc_map, p, &vtmp, remap ) )
580                         {
581                                 return -1;
582                         }
583                         
584                         fstr->bv_len += vtmp.bv_len;
585                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
586
587                         snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
588                                 /*"("*/ "%s)", vtmp.bv_val );
589
590                         ch_free( vtmp.bv_val );
591                 }
592
593                 break;
594
595         case LDAP_FILTER_EXT: {
596                 if ( f->f_mr_desc ) {
597                         if ( map_attr_value( at_map, oc_map, f->f_mr_desc, &atmp,
598                                                 &f->f_mr_value, &vtmp, remap ) )
599                         {
600                                 return -1;
601                         }
602
603                 } else {
604                         atmp.bv_len = 0;
605                         atmp.bv_val = "";
606                         
607                         filter_escape_value( &f->f_mr_value, &vtmp );
608                 }
609                         
610
611                 fstr->bv_len = atmp.bv_len +
612                         ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
613                         ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
614                         vtmp.bv_len + ( sizeof("(:=)") - 1 );
615                 fstr->bv_val = malloc( fstr->bv_len + 1 );
616
617                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
618                         atmp.bv_val,
619                         f->f_mr_dnattrs ? ":dn" : "",
620                         f->f_mr_rule_text.bv_len ? ":" : "",
621                         f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
622                         vtmp.bv_val );
623                 ber_memfree( vtmp.bv_val );
624                 } break;
625
626         case SLAPD_FILTER_COMPUTED:
627                 ber_str2bv(
628                         f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
629                         f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
630                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
631                         "(?=error)",
632                         f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
633                         f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
634                         f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
635                         sizeof("(?=error)")-1,
636                         1, fstr );
637                 break;
638
639         default:
640                 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
641                 break;
642         }
643
644         return 0;
645 }