]> git.sur5r.net Git - openldap/blob - servers/slapd/overlays/rwm.c
9c8e814ae66a2b44b47d2a0728a9fb94c28259d1
[openldap] / servers / slapd / overlays / rwm.c
1 /* rwm.c - rewrite/remap operations */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003 The OpenLDAP Foundation.
6  * Portions Copyright 2003 Pierangelo Masarati.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17
18 #include "portable.h"
19
20 #include <stdio.h>
21
22 #include "slap.h"
23 #include "rwm.h"
24
25 static int
26 rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie )
27 {
28         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
29         struct ldaprwmap        *rwmap = 
30                         (struct ldaprwmap *)on->on_bi.bi_private;
31
32         struct berval           dn, ndn, mdn = { 0, NULL };
33         int                     rc = 0;
34         dncookie                dc;
35
36         /*
37          * Rewrite the bind dn if needed
38          */
39         dc.rwmap = rwmap;
40 #ifdef ENABLE_REWRITE
41         dc.conn = op->o_conn;
42         dc.rs = rs;
43         dc.ctx = (char *)cookie;
44 #else
45         dc.tofrom = ((int *)cookie)[0];
46         dc.normalized = 0;
47 #endif
48
49         rc = rwm_dn_massage( &dc, &op->o_req_dn, &mdn );
50         if ( rc != LDAP_SUCCESS ) {
51                 return rc;
52         }
53
54         if ( mdn.bv_val == op->o_req_dn.bv_val ) {
55                 return LDAP_SUCCESS;
56         }
57
58         rc = dnPrettyNormal( NULL, &mdn, &dn, &ndn, op->o_tmpmemctx );
59         if ( rc != LDAP_SUCCESS ) {
60                 return rc;
61         }
62
63         if ( mdn.bv_val != dn.bv_val ) {
64                 ch_free( mdn.bv_val );
65         }
66
67         op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
68         op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
69
70         op->o_req_dn = dn;
71         op->o_req_ndn = ndn;
72
73         return LDAP_SUCCESS;
74 }
75
76 static int
77 rwm_bind( Operation *op, SlapReply *rs )
78 {
79         int     rc;
80
81 #ifdef ENABLE_REWRITE
82         rc = rwm_op_dn_massage( op, rs, "bindDn" );
83 #else
84         rc = 1;
85         rc = rwm_op_dn_massage( op, rs, &rc );
86 #endif
87         if ( rc != LDAP_SUCCESS ) {
88                 return rc;
89         }
90
91         return SLAP_CB_CONTINUE;
92 }
93
94 static int
95 rwm_add( Operation *op, SlapReply *rs )
96 {
97         int     rc;
98
99 #ifdef ENABLE_REWRITE
100         rc = rwm_op_dn_massage( op, rs, "addDn" );
101 #else
102         rc = 1;
103         rc = rwm_op_dn_massage( op, rs, &rc );
104 #endif
105         if ( rc != LDAP_SUCCESS ) {
106                 return rc;
107         }
108
109         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
110         return SLAP_CB_CONTINUE;
111 }
112
113 static int
114 rwm_delete( Operation *op, SlapReply *rs )
115 {
116         int     rc;
117
118 #ifdef ENABLE_REWRITE
119         rc = rwm_op_dn_massage( op, rs, "deleteDn" );
120 #else
121         rc = 1;
122         rc = rwm_op_dn_massage( op, rs, &rc );
123 #endif
124         if ( rc != LDAP_SUCCESS ) {
125                 return rc;
126         }
127
128         return SLAP_CB_CONTINUE;
129 }
130
131 static int
132 rwm_modrdn( Operation *op, SlapReply *rs )
133 {
134         int     rc;
135
136 #ifdef ENABLE_REWRITE
137         rc = rwm_op_dn_massage( op, rs, "renameDn" );
138 #else
139         rc = 1;
140         rc = rwm_op_dn_massage( op, rs, &rc );
141 #endif
142         if ( rc != LDAP_SUCCESS ) {
143                 return rc;
144         }
145
146         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
147         return SLAP_CB_CONTINUE;
148 }
149
150 static int
151 rwm_modify( Operation *op, SlapReply *rs )
152 {
153         int     rc;
154
155 #ifdef ENABLE_REWRITE
156         rc = rwm_op_dn_massage( op, rs, "modifyDn" );
157 #else
158         rc = 1;
159         rc = rwm_op_dn_massage( op, rs, &rc );
160 #endif
161         if ( rc != LDAP_SUCCESS ) {
162                 return rc;
163         }
164
165         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
166         return SLAP_CB_CONTINUE;
167 }
168
169 static int
170 rwm_compare( Operation *op, SlapReply *rs )
171 {
172         int     rc;
173
174 #ifdef ENABLE_REWRITE
175         rc = rwm_op_dn_massage( op, rs, "compareDn" );
176 #else
177         rc = 1;
178         rc = rwm_op_dn_massage( op, rs, &rc );
179 #endif
180         if ( rc != LDAP_SUCCESS ) {
181                 return rc;
182         }
183
184         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
185         return SLAP_CB_CONTINUE;
186 }
187
188 static int
189 rwm_search( Operation *op, SlapReply *rs )
190 {
191         int     rc;
192
193 #ifdef ENABLE_REWRITE
194         rc = rwm_op_dn_massage( op, rs, "searchDn" );
195 #else
196         rc = 1;
197         rc = rwm_op_dn_massage( op, rs, &rc );
198 #endif
199         if ( rc != LDAP_SUCCESS ) {
200                 return rc;
201         }
202
203         /* TODO: rewrite/map filter & attrs */
204         return SLAP_CB_CONTINUE;
205 }
206
207 static int
208 rwm_extended( Operation *op, SlapReply *rs )
209 {
210         int     rc;
211
212 #ifdef ENABLE_REWRITE
213         rc = rwm_op_dn_massage( op, rs, "extendedDn" );
214 #else
215         rc = 1;
216         rc = rwm_op_dn_massage( op, rs, &rc );
217 #endif
218         if ( rc != LDAP_SUCCESS ) {
219                 return rc;
220         }
221
222         /* TODO: rewrite/map extended data ? ... */
223         return 0;
224 }
225
226 static int
227 rwm_matched( Operation *op, SlapReply *rs )
228 {
229         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
230         struct ldaprwmap        *rwmap = 
231                         (struct ldaprwmap *)on->on_bi.bi_private;
232
233         struct berval           dn, mdn;
234         dncookie                dc;
235
236         if ( rs->sr_matched == NULL ) {
237                 return SLAP_CB_CONTINUE;
238         }
239
240         dc.rwmap = rwmap;
241 #ifdef ENABLE_REWRITE
242         dc.conn = op->o_conn;
243         dc.rs = rs;
244         dc.ctx = "matchedDn";
245 #else
246         dc.tofrom = 0;
247         dc.normalized = 0;
248 #endif
249         ber_str2bv( rs->sr_matched, 0, 0, &dn );
250         rwm_dn_massage( &dc, &dn, &mdn );
251
252         if ( mdn.bv_val != dn.bv_val ) {
253                 if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
254                         ch_free( (void *)rs->sr_matched );
255                 } else {
256                         rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
257                 }
258                 rs->sr_matched = mdn.bv_val;
259         }
260         
261         return SLAP_CB_CONTINUE;
262 }
263
264 static int
265 rwm_send_entry( Operation *op, SlapReply *rs )
266 {
267         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
268         struct ldaprwmap        *rwmap = 
269                         (struct ldaprwmap *)on->on_bi.bi_private;
270
271         Entry           *e = NULL;
272         struct berval   dn = { 0, NULL }, ndn = { 0, NULL };
273         dncookie        dc;
274         int             rc = SLAP_CB_CONTINUE;
275
276         assert( rs->sr_entry );
277
278         e = rs->sr_entry;
279
280         /*
281          * Rewrite the dn of the result, if needed
282          */
283         dc.rwmap = rwmap;
284 #ifdef ENABLE_REWRITE
285         dc.conn = op->o_conn;
286         dc.rs = NULL; 
287         dc.ctx = "searchResultDN";
288 #else
289         dc.tofrom = 0;
290         dc.normalized = 0;
291 #endif
292         if ( rwm_dn_massage( &dc, &e->e_name, &dn ) ) {
293                 return LDAP_OTHER;
294         }
295
296         if ( e->e_name.bv_val == dn.bv_val ) {
297                 return SLAP_CB_CONTINUE;
298         }
299
300         /*
301          * Note: this may fail if the target host(s) schema differs
302          * from the one known to the meta, and a DN with unknown
303          * attributes is returned.
304          */
305         if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ) != LDAP_SUCCESS ) {
306                 if ( dn.bv_val != e->e_name.bv_val ) {
307                         ch_free( dn.bv_val );
308                 }
309                 rc = LDAP_INVALID_DN_SYNTAX;
310                 goto fail;
311         }
312
313         if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
314                 e = entry_dup( e );
315                 if ( e == NULL ) {
316                         goto fail;
317                 }
318                 rs->sr_flags |= ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED );
319         }
320
321         free( e->e_name.bv_val );
322         free( e->e_nname.bv_val );
323
324         e->e_name = dn;
325         e->e_nname = ndn;
326
327         rs->sr_entry = e;
328
329         /* TODO: map entry attribute types, objectclasses 
330          * and dn-valued attribute values */
331         
332         return SLAP_CB_CONTINUE;
333
334 fail:;
335         if ( dn.bv_val && ( dn.bv_val != e->e_name.bv_val ) ) {
336                 ch_free( dn.bv_val );
337         }
338
339         if ( ndn.bv_val ) {
340                 ch_free( ndn.bv_val );
341         }
342
343         return rc;
344 }
345
346 static int
347 rwm_rw_config(
348     BackendDB   *be,
349     const char  *fname,
350     int         lineno,
351     int         argc,
352     char        **argv
353 )
354 {
355 #ifdef ENABLE_REWRITE
356         slap_overinst           *on = (slap_overinst *) be->bd_info;
357         struct ldaprwmap        *rwmap = 
358                         (struct ldaprwmap *)on->on_bi.bi_private;
359
360         return rewrite_parse( rwmap->rwm_rw,
361                                 fname, lineno, argc, argv );
362
363 #else /* !ENABLE_REWRITE */
364         fprintf( stderr, "%s: line %d: rewrite capabilities "
365                         "are not enabled\n", fname, lineno );
366 #endif /* !ENABLE_REWRITE */
367                 
368         return 0;
369 }
370
371 static int
372 rwm_suffixmassage_config(
373     BackendDB   *be,
374     const char  *fname,
375     int         lineno,
376     int         argc,
377     char        **argv
378 )
379 {
380         slap_overinst           *on = (slap_overinst *) be->bd_info;
381         struct ldaprwmap        *rwmap = 
382                         (struct ldaprwmap *)on->on_bi.bi_private;
383
384         struct berval   bvnc, nvnc, pvnc, brnc, nrnc, prnc;
385 #ifdef ENABLE_REWRITE
386         int             rc;
387 #endif /* ENABLE_REWRITE */
388                 
389         /*
390          * syntax:
391          * 
392          *      suffixmassage <suffix> <massaged suffix>
393          *
394          * the <suffix> field must be defined as a valid suffix
395          * (or suffixAlias?) for the current database;
396          * the <massaged suffix> shouldn't have already been
397          * defined as a valid suffix or suffixAlias for the 
398          * current server
399          */
400         if ( argc != 3 ) {
401                 fprintf( stderr, "%s: line %d: syntax is"
402                                " \"suffixMassage <suffix>"
403                                " <massaged suffix>\"\n",
404                         fname, lineno );
405                 return 1;
406         }
407                 
408         ber_str2bv( argv[1], 0, 0, &bvnc );
409         if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
410                 fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
411                         fname, lineno, bvnc.bv_val );
412                 return 1;
413         }
414
415         ber_str2bv( argv[2], 0, 0, &brnc );
416         if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
417                 fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
418                                 fname, lineno, brnc.bv_val );
419                 free( nvnc.bv_val );
420                 free( pvnc.bv_val );
421                 return 1;
422         }
423
424 #ifdef ENABLE_REWRITE
425         /*
426          * The suffix massaging is emulated 
427          * by means of the rewrite capabilities
428          */
429         rc = suffix_massage_config( rwmap->rwm_rw,
430                         &pvnc, &nvnc, &prnc, &nrnc );
431         free( nvnc.bv_val );
432         free( pvnc.bv_val );
433         free( nrnc.bv_val );
434         free( prnc.bv_val );
435
436         return( rc );
437
438 #else /* !ENABLE_REWRITE */
439         ber_bvarray_add( &rwmap->rwm_suffix_massage, &pvnc );
440         ber_bvarray_add( &rwmap->rwm_suffix_massage, &nvnc );
441                 
442         ber_bvarray_add( &rwmap->rwm_suffix_massage, &prnc );
443         ber_bvarray_add( &rwmap->rwm_suffix_massage, &nrnc );
444 #endif /* !ENABLE_REWRITE */
445
446         return 0;
447 }
448
449 static int
450 rwm_m_config(
451     BackendDB   *be,
452     const char  *fname,
453     int         lineno,
454     int         argc,
455     char        **argv
456 )
457 {
458         slap_overinst           *on = (slap_overinst *) be->bd_info;
459         struct ldaprwmap        *rwmap = 
460                         (struct ldaprwmap *)on->on_bi.bi_private;
461
462         /* objectclass/attribute mapping */
463         return rwm_map_config( &rwmap->rwm_oc,
464                         &rwmap->rwm_at,
465                         fname, lineno, argc, argv );
466 }
467
468 static int
469 rwm_response( Operation *op, SlapReply *rs )
470 {
471         int     rc;
472
473         if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
474                 return rwm_send_entry( op, rs );
475         }
476
477         switch( op->o_tag ) {
478         case LDAP_REQ_BIND:
479         case LDAP_REQ_ADD:
480         case LDAP_REQ_DELETE:
481         case LDAP_REQ_MODRDN:
482         case LDAP_REQ_MODIFY:
483         case LDAP_REQ_COMPARE:
484         case LDAP_REQ_SEARCH:
485         case LDAP_REQ_EXTENDED:
486                 rc = rwm_matched( op, rs );
487                 break;
488         default:
489                 rc = SLAP_CB_CONTINUE;
490                 break;
491         }
492
493         return rc;
494 }
495
496 static int
497 rwm_config(
498     BackendDB   *be,
499     const char  *fname,
500     int         lineno,
501     int         argc,
502     char        **argv
503 )
504 {
505         int             rc = 0;
506
507         if ( strncasecmp( argv[0], "rewrite", sizeof("rewrite") - 1) == 0 ) {
508                 rc = rwm_rw_config( be, fname, lineno, argc, argv );
509
510         } else if (strcasecmp( argv[0], "map" ) == 0 ) {
511                 rc = rwm_m_config( be, fname, lineno, argc, argv );
512
513         } else if (strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
514                 rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
515
516         } else {
517                 rc = SLAP_CONF_UNKNOWN;
518         }
519
520         return rc;
521 }
522
523 static int
524 rwm_init(
525         BackendDB *be
526 )
527 {
528         slap_overinst           *on = (slap_overinst *) be->bd_info;
529         struct ldapmapping      *mapping = NULL;
530         struct ldaprwmap        *rwmap;
531
532         rwmap = (struct ldaprwmap *)ch_malloc(sizeof(struct ldaprwmap));
533         memset(rwmap, 0, sizeof(struct ldaprwmap));
534
535 #ifdef ENABLE_REWRITE
536         rwmap->rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
537         if ( rwmap->rwm_rw == NULL ) {
538                 ch_free( rwmap );
539                 return -1;
540         }
541 #endif /* ENABLE_REWRITE */
542
543         rwm_map_init( &rwmap->rwm_oc, &mapping );
544         rwm_map_init( &rwmap->rwm_at, &mapping );
545
546         on->on_bi.bi_private = (void *)rwmap;
547
548         return 0;
549 }
550
551 static int
552 rwm_destroy(
553         BackendDB *be
554 )
555 {
556         slap_overinst   *on = (slap_overinst *) be->bd_info;
557         int             rc = 0;
558
559         if ( on->on_bi.bi_private ) {
560                 struct ldaprwmap        *rwmap = 
561                         (struct ldaprwmap *)on->on_bi.bi_private;
562
563 #ifdef ENABLE_REWRITE
564                 if (rwmap->rwm_rw) {
565                         rewrite_info_delete( &rwmap->rwm_rw );
566                 }
567 #else /* !ENABLE_REWRITE */
568                 if ( rwmap->lrwm_suffix_massage ) {
569                         ber_bvarray_free( rwmap->rwm_suffix_massage );
570                 }
571 #endif /* !ENABLE_REWRITE */
572
573                 avl_free( rwmap->rwm_oc.remap, NULL );
574                 avl_free( rwmap->rwm_oc.map, mapping_free );
575                 avl_free( rwmap->rwm_at.remap, NULL );
576                 avl_free( rwmap->rwm_at.map, mapping_free );
577         }
578
579         return rc;
580 }
581
582 static slap_overinst rwm = { { NULL } };
583
584 int
585 init_module(void)
586 {
587         memset( &rwm, 0, sizeof(slap_overinst) );
588
589         rwm.on_bi.bi_type = "rewrite-remap";
590         rwm.on_bi.bi_db_init = rwm_init;
591         rwm.on_bi.bi_db_config = rwm_config;
592         rwm.on_bi.bi_db_destroy = rwm_destroy;
593
594         rwm.on_bi.bi_op_bind = rwm_bind;
595         rwm.on_bi.bi_op_search = rwm_search;
596         rwm.on_bi.bi_op_compare = rwm_compare;
597         rwm.on_bi.bi_op_modify = rwm_modify;
598         rwm.on_bi.bi_op_modrdn = rwm_modrdn;
599         rwm.on_bi.bi_op_add = rwm_add;
600         rwm.on_bi.bi_op_delete = rwm_delete;
601         rwm.on_bi.bi_extended = rwm_extended;
602
603         rwm.on_response = rwm_response;
604
605         return overlay_register( &rwm );
606 }
607