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