]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/map.c
Remove attribute.c, group.c from build
[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 char **
218 ldap_back_map_attrs(
219                 struct ldapmap *at_map,
220                 AttributeName *an,
221                 int remap
222 )
223 {
224         int i, j;
225         char **na;
226         struct berval mapped;
227
228         if (an == NULL)
229                 return(NULL);
230
231         for (i = 0; an[i].an_name.bv_val; i++) {
232                 /*  */
233         }
234
235         na = (char **)ch_calloc( i + 1, sizeof(char *) );
236         if (na == NULL)
237                 return(NULL);
238
239         for (i = j = 0; an[i].an_name.bv_val; i++) {
240                 ldap_back_map(at_map, &an[i].an_name, &mapped, remap);
241                 if (mapped.bv_val != NULL && mapped.bv_val != '\0')
242                         na[j++] = mapped.bv_val;
243         }
244         if (j == 0 && i != 0)
245                 na[j++] = LDAP_NO_ATTRS;
246         na[j] = NULL;
247
248         return(na);
249 }
250
251 #ifdef ENABLE_REWRITE
252
253 static int
254 map_attr_value_(
255                 struct rewrite_info     *info,
256                 void                    *cookie,
257                 struct ldapmap          *at_map,
258                 struct ldapmap          *oc_map,
259                 AttributeDescription    *ad,
260                 struct berval           *mapped_attr,
261                 struct berval           *value,
262                 struct berval           *mapped_value,
263                 int                     remap )
264 {
265         struct berval           vtmp;
266         int                     freeval = 0;
267
268         ldap_back_map( at_map, &ad->ad_cname, mapped_attr, remap );
269         if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
270                 /*
271                  * FIXME: are we sure we need to search oc_map if at_map fails?
272                  */
273                 ldap_back_map( oc_map, &ad->ad_cname, mapped_attr, remap );
274                 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
275                         *mapped_attr = ad->ad_cname;
276                 }
277         }
278
279         if ( value == NULL ) {
280                 return 0;
281         }
282
283         if ( strcmp( ad->ad_type->sat_syntax->ssyn_oid, SLAPD_DN_SYNTAX ) == 0 )
284         {
285                 switch ( rewrite_session( info, "searchFilter",
286                                         value->bv_val, cookie, &vtmp.bv_val ) ) {
287                 case REWRITE_REGEXEC_OK:
288                         if ( vtmp.bv_val == NULL ) {
289                                 vtmp = *value;
290                         } else {
291                                 vtmp.bv_len = strlen( vtmp.bv_val );
292                                 freeval = 1;
293                         }
294 #ifdef NEW_LOGGING
295                         LDAP_LOG( BACK_LDAP, DETAIL1, 
296                                 "[rw] searchFilter: \"%s\" -> \"%s\"\n", 
297                                 value->bv_val, vtmp.bv_val, 0 );
298 #else /* !NEW_LOGGING */
299                         Debug( LDAP_DEBUG_ARGS, "rw> searchFilter: \"%s\" -> \"%s\"\n%s",
300                                         value->bv_val, vtmp.bv_val, "" );
301 #endif /* !NEW_LOGGING */
302                         break;
303
304                 
305                 case REWRITE_REGEXEC_UNWILLING:
306                         return -1;
307
308                 case REWRITE_REGEXEC_ERR:
309                         return -1;
310                 }
311
312         } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
313                 ldap_back_map( oc_map, value, &vtmp, remap );
314                 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
315                         vtmp = *value;
316                 }
317                 
318         } else {
319                 vtmp = *value;
320         }
321
322         filter_escape_value( &vtmp, mapped_value );
323
324         if ( freeval ) {
325                 ber_memfree( vtmp.bv_val );
326         }
327         
328         return 0;
329 }
330
331 #define map_attr_value(at_map, oc_map, ad, mapped_attr, value, mapped_value, remap) \
332         map_attr_value_(info, cookie, (at_map), (oc_map), (ad), (mapped_attr), (value), (mapped_value), (remap))
333 #define ldap_back_filter_map_rewrite(at_map, oc_map, f, fstr, remap) \
334         ldap_back_filter_map_rewrite_(info, cookie, (at_map), (oc_map), (f), (fstr), (remap))
335
336 #else /* ! ENABLE_REWRITE */
337
338 static int
339 map_attr_value_(
340                 struct ldapmap          *at_map,
341                 struct ldapmap          *oc_map,
342                 AttributeDescription    *ad,
343                 struct berval           *mapped_attr,
344                 struct berval           *value,
345                 struct berval           *mapped_value,
346                 int                     remap )
347 {
348         struct berval           vtmp;
349
350         ldap_back_map( at_map, &ad->ad_cname, mapped_attr, remap );
351         if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0') {
352                 /*
353                  * FIXME: are we sure we need to search oc_map if at_map fails?
354                  */
355                 ldap_back_map( oc_map, &ad->ad_cname, mapped_attr, remap );
356                 if ( mapped_attr->bv_val == NULL || mapped_attr->bv_val[0] == '\0' ) {
357                         *mapped_attr = ad->ad_cname;
358                 }
359         }
360
361         if ( value == NULL ) {
362                 return 0;
363         }
364
365         if ( strcmp( ad->ad_type->sat_syntax->ssyn_oid, SLAPD_DN_SYNTAX ) == 0 )
366         {
367                 /* FIXME: use suffix massage capabilities */
368                 vtmp = *value;
369
370         } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
371                 ldap_back_map( oc_map, value, &vtmp, remap );
372                 if ( vtmp.bv_val == NULL || vtmp.bv_val[0] == '\0' ) {
373                         vtmp = *value;
374                 }
375                 
376         } else {
377                 vtmp = *value;
378         }
379
380         filter_escape_value( &vtmp, mapped_value );
381
382         return 0;
383 }
384
385 #define map_attr_value(at_map, oc_map, ad, mapped_attr, value, mapped_value, remap) \
386         map_attr_value_((at_map), (oc_map), (ad), (mapped_attr), (value), (mapped_value), (remap))
387 #define ldap_back_filter_map_rewrite(at_map, oc_map, f, fstr, remap) \
388         ldap_back_filter_map_rewrite_((at_map), (oc_map), (f), (fstr), (remap))
389
390 #endif /* ! ENABLE_REWRITE */
391
392 int
393 ldap_back_filter_map_rewrite_(
394 #ifdef ENABLE_REWRITE
395                 struct rewrite_info     *info,
396                 void                    *cookie,
397 #endif /* ENABLE_REWRITE */
398                 struct ldapmap          *at_map,
399                 struct ldapmap          *oc_map,
400                 Filter                  *f,
401                 struct berval           *fstr,
402                 int                     remap )
403 {
404         int             i;
405         Filter          *p;
406         struct berval   atmp;
407         struct berval   vtmp;
408         ber_len_t       len;
409
410         if ( f == NULL ) {
411                 ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
412                 return -1;
413         }
414
415         switch ( f->f_choice ) {
416         case LDAP_FILTER_EQUALITY:
417                 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
418                                         &f->f_av_value, &vtmp, remap ) )
419                 {
420                         return -1;
421                 }
422
423                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
424                         + ( sizeof("(=)") - 1 );
425                 fstr->bv_val = malloc( fstr->bv_len + 1 );
426
427                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
428                         atmp.bv_val, vtmp.bv_val );
429
430                 ber_memfree( vtmp.bv_val );
431                 break;
432
433         case LDAP_FILTER_GE:
434                 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
435                                 &f->f_av_value, &vtmp, remap ) )
436                 {
437                         return -1;
438                 }
439
440                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
441                         + ( sizeof("(>=)") - 1 );
442                 fstr->bv_val = malloc( fstr->bv_len + 1 );
443
444                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
445                         atmp.bv_val, vtmp.bv_val );
446
447                 ber_memfree( vtmp.bv_val );
448                 break;
449
450         case LDAP_FILTER_LE:
451                 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
452                                         &f->f_av_value, &vtmp, remap ) )
453                 {
454                         return -1;
455                 }
456
457                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
458                         + ( sizeof("(<=)") - 1 );
459                 fstr->bv_val = malloc( fstr->bv_len + 1 );
460
461                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
462                         atmp.bv_val, vtmp.bv_val );
463
464                 ber_memfree( vtmp.bv_val );
465                 break;
466
467         case LDAP_FILTER_APPROX:
468                 if ( map_attr_value( at_map, oc_map, f->f_av_desc, &atmp,
469                                         &f->f_av_value, &vtmp, remap ) )
470                 {
471                         return -1;
472                 }
473
474                 fstr->bv_len = atmp.bv_len + vtmp.bv_len
475                         + ( sizeof("(~=)") - 1 );
476                 fstr->bv_val = malloc( fstr->bv_len + 1 );
477
478                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
479                         atmp.bv_val, vtmp.bv_val );
480
481                 ber_memfree( vtmp.bv_val );
482                 break;
483
484         case LDAP_FILTER_SUBSTRINGS:
485                 if ( map_attr_value( at_map, oc_map, f->f_sub_desc, &atmp,
486                                         NULL, NULL, remap ) )
487                 {
488                         return -1;
489                 }
490
491                 /* cannot be a DN ... */
492
493                 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
494                 fstr->bv_val = malloc( fstr->bv_len + 128 );
495
496                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
497                         atmp.bv_val );
498
499                 if ( f->f_sub_initial.bv_val != NULL ) {
500                         len = fstr->bv_len;
501
502                         filter_escape_value( &f->f_sub_initial, &vtmp );
503
504                         fstr->bv_len += vtmp.bv_len;
505                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
506
507                         snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
508                                 /* "(attr=" */ "%s*)",
509                                 vtmp.bv_val );
510
511                         ber_memfree( vtmp.bv_val );
512                 }
513
514                 if ( f->f_sub_any != NULL ) {
515                         for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
516                                 len = fstr->bv_len;
517                                 filter_escape_value( &f->f_sub_any[i], &vtmp );
518
519                                 fstr->bv_len += vtmp.bv_len + 1;
520                                 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
521
522                                 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
523                                         /* "(attr=[init]*[any*]" */ "%s*)",
524                                         vtmp.bv_val );
525                                 ber_memfree( vtmp.bv_val );
526                         }
527                 }
528
529                 if ( f->f_sub_final.bv_val != NULL ) {
530                         len = fstr->bv_len;
531
532                         filter_escape_value( &f->f_sub_final, &vtmp );
533
534                         fstr->bv_len += vtmp.bv_len;
535                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
536
537                         snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
538                                 /* "(attr=[init*][any*]" */ "%s)",
539                                 vtmp.bv_val );
540
541                         ber_memfree( vtmp.bv_val );
542                 }
543
544                 break;
545
546         case LDAP_FILTER_PRESENT:
547                 if ( map_attr_value( at_map, oc_map, f->f_desc, &atmp,
548                                         NULL, NULL, remap ) )
549                 {
550                         return -1;
551                 }
552
553                 fstr->bv_len = atmp.bv_len + ( sizeof("(=*)") - 1 );
554                 fstr->bv_val = malloc( fstr->bv_len + 1 );
555
556                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
557                         atmp.bv_val );
558                 break;
559
560         case LDAP_FILTER_AND:
561         case LDAP_FILTER_OR:
562         case LDAP_FILTER_NOT:
563                 fstr->bv_len = sizeof("(%)") - 1;
564                 fstr->bv_val = malloc( fstr->bv_len + 128 );
565
566                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
567                         f->f_choice == LDAP_FILTER_AND ? '&' :
568                         f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
569
570                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
571                         len = fstr->bv_len;
572
573                         if ( ldap_back_filter_map_rewrite( at_map, oc_map, p, &vtmp, remap ) )
574                         {
575                                 return -1;
576                         }
577                         
578                         fstr->bv_len += vtmp.bv_len;
579                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
580
581                         snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
582                                 /*"("*/ "%s)", vtmp.bv_val );
583
584                         ch_free( vtmp.bv_val );
585                 }
586
587                 break;
588
589         case LDAP_FILTER_EXT: {
590                 if ( f->f_mr_desc ) {
591                         if ( map_attr_value( at_map, oc_map, f->f_mr_desc, &atmp,
592                                                 &f->f_mr_value, &vtmp, remap ) )
593                         {
594                                 return -1;
595                         }
596
597                 } else {
598                         atmp.bv_len = 0;
599                         atmp.bv_val = "";
600                         
601                         filter_escape_value( &f->f_mr_value, &vtmp );
602                 }
603                         
604
605                 fstr->bv_len = atmp.bv_len +
606                         ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
607                         ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
608                         vtmp.bv_len + ( sizeof("(:=)") - 1 );
609                 fstr->bv_val = malloc( fstr->bv_len + 1 );
610
611                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
612                         atmp.bv_val,
613                         f->f_mr_dnattrs ? ":dn" : "",
614                         f->f_mr_rule_text.bv_len ? ":" : "",
615                         f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
616                         vtmp.bv_val );
617                 ber_memfree( vtmp.bv_val );
618                 } break;
619
620         case SLAPD_FILTER_COMPUTED:
621                 ber_str2bv(
622                         f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
623                         f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
624                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
625                         "(?=error)",
626                         f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
627                         f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
628                         f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
629                         sizeof("(?=error)")-1,
630                         1, fstr );
631                 break;
632
633         default:
634                 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
635                 break;
636         }
637
638         return 0;
639 }